From 1d22b6033ea113a4c3850dfa2c0770885c81aec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvin=20=C5=A0ipraga?= <alsi@bang-olufsen.dk> Date: Sun, 12 Jun 2022 16:48:53 +0200 Subject: [PATCH 001/396] drm: bridge: adv7511: fix CEC power down control register offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ADV7511_REG_CEC_CTRL = 0xE2 register is part of the main register map - not the CEC register map. As such, we shouldn't apply an offset to the register address. Doing so will cause us to address a bogus register for chips with a CEC register map offset (e.g. ADV7533). Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220612144854.2223873-2-alvin@pqrs.dk --- drivers/gpu/drm/bridge/adv7511/adv7511.h | 5 +---- drivers/gpu/drm/bridge/adv7511/adv7511_cec.c | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h index a031a0cd1f18..94de73cbeb2d 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h @@ -394,10 +394,7 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1); #else static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) { - unsigned int offset = adv7511->type == ADV7533 ? - ADV7533_REG_CEC_OFFSET : 0; - - regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, ADV7511_CEC_CTRL_POWER_DOWN); return 0; } diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c index 0b266f28f150..99964f5a5457 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c @@ -359,7 +359,7 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) goto err_cec_alloc; } - regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0); + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0); /* cec soft reset */ regmap_write(adv7511->regmap_cec, ADV7511_REG_CEC_SOFT_RESET + offset, 0x01); @@ -386,7 +386,7 @@ err_cec_alloc: dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n", ret); err_cec_parse_dt: - regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, ADV7511_CEC_CTRL_POWER_DOWN); return ret == -EPROBE_DEFER ? ret : 0; } From 40cdb02cb9f965732eb543d47f15bef8d10f0f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvin=20=C5=A0ipraga?= <alsi@bang-olufsen.dk> Date: Sun, 12 Jun 2022 16:48:54 +0200 Subject: [PATCH 002/396] drm: bridge: adv7511: unregister cec i2c device after cec adapter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cec_unregister_adapter() assumes that the underlying adapter ops are callable. For example, if the CEC adapter currently has a valid physical address, then the unregistration procedure will invalidate the physical address by setting it to f.f.f.f. Whence the following kernel oops observed after removing the adv7511 module: Unable to handle kernel execution of user memory at virtual address 0000000000000000 Internal error: Oops: 86000004 [#1] PREEMPT_RT SMP Call trace: 0x0 adv7511_cec_adap_log_addr+0x1ac/0x1c8 [adv7511] cec_adap_unconfigure+0x44/0x90 [cec] __cec_s_phys_addr.part.0+0x68/0x230 [cec] __cec_s_phys_addr+0x40/0x50 [cec] cec_unregister_adapter+0xb4/0x118 [cec] adv7511_remove+0x60/0x90 [adv7511] i2c_device_remove+0x34/0xe0 device_release_driver_internal+0x114/0x1f0 driver_detach+0x54/0xe0 bus_remove_driver+0x60/0xd8 driver_unregister+0x34/0x60 i2c_del_driver+0x2c/0x68 adv7511_exit+0x1c/0x67c [adv7511] __arm64_sys_delete_module+0x154/0x288 invoke_syscall+0x48/0x100 el0_svc_common.constprop.0+0x48/0xe8 do_el0_svc+0x28/0x88 el0_svc+0x1c/0x50 el0t_64_sync_handler+0xa8/0xb0 el0t_64_sync+0x15c/0x160 Code: bad PC value ---[ end trace 0000000000000000 ]--- Protect against this scenario by unregistering i2c_cec after unregistering the CEC adapter. Duly disable the CEC clock afterwards too. Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220612144854.2223873-3-alvin@pqrs.dk --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 38bf28720f3a..6031bdd92342 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -1340,9 +1340,6 @@ static int adv7511_remove(struct i2c_client *i2c) { struct adv7511 *adv7511 = i2c_get_clientdata(i2c); - i2c_unregister_device(adv7511->i2c_cec); - clk_disable_unprepare(adv7511->cec_clk); - adv7511_uninit_regulators(adv7511); drm_bridge_remove(&adv7511->bridge); @@ -1350,6 +1347,8 @@ static int adv7511_remove(struct i2c_client *i2c) adv7511_audio_exit(adv7511); cec_unregister_adapter(adv7511->cec_adap); + i2c_unregister_device(adv7511->i2c_cec); + clk_disable_unprepare(adv7511->cec_clk); i2c_unregister_device(adv7511->i2c_packet); i2c_unregister_device(adv7511->i2c_edid); From 540dfd188ea2940582841c1c220bd035a7db0e51 Mon Sep 17 00:00:00 2001 From: Jianglei Nie <niejianglei2021@163.com> Date: Tue, 5 Jul 2022 21:25:46 +0800 Subject: [PATCH 003/396] drm/nouveau: fix a use-after-free in nouveau_gem_prime_import_sg_table() nouveau_bo_init() is backed by ttm_bo_init() and ferries its return code back to the caller. On failures, ttm will call nouveau_bo_del_ttm() and free the memory.Thus, when nouveau_bo_init() returns an error, the gem object has already been released. Then the call to nouveau_bo_ref() will use the freed "nvbo->bo" and lead to a use-after-free bug. We should delete the call to nouveau_bo_ref() to avoid the use-after-free. Signed-off-by: Jianglei Nie <niejianglei2021@163.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Lyude Paul <lyude@redhat.com> Fixes: 019cbd4a4feb ("drm/nouveau: Initialize GEM object before TTM object") Cc: Thierry Reding <treding@nvidia.com> Cc: <stable@vger.kernel.org> # v5.4+ Link: https://patchwork.freedesktop.org/patch/msgid/20220705132546.2247677-1-niejianglei2021@163.com --- drivers/gpu/drm/nouveau/nouveau_prime.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 347488685f74..9608121e49b7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -71,7 +71,6 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, ret = nouveau_bo_init(nvbo, size, align, NOUVEAU_GEM_DOMAIN_GART, sg, robj); if (ret) { - nouveau_bo_ref(NULL, &nvbo); obj = ERR_PTR(ret); goto unlock; } From 6dc548745d5b5102e3c53dc5097296ac270b6c69 Mon Sep 17 00:00:00 2001 From: Jianglei Nie <niejianglei2021@163.com> Date: Tue, 5 Jul 2022 17:43:06 +0800 Subject: [PATCH 004/396] drm/nouveau/nouveau_bo: fix potential memory leak in nouveau_bo_alloc() nouveau_bo_alloc() allocates a memory chunk for "nvbo" with kzalloc(). When some error occurs, "nvbo" should be released. But when WARN_ON(pi < 0)) equals true, the function return ERR_PTR without releasing the "nvbo", which will lead to a memory leak. We should release the "nvbo" with kfree() if WARN_ON(pi < 0)) equals true. Signed-off-by: Jianglei Nie <niejianglei2021@163.com> Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220705094306.2244103-1-niejianglei2021@163.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 05076e530e7d..d0887438b07e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -281,8 +281,10 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, break; } - if (WARN_ON(pi < 0)) + if (WARN_ON(pi < 0)) { + kfree(nvbo); return ERR_PTR(-EINVAL); + } /* Disable compression if suitable settings couldn't be found. */ if (nvbo->comp && !vmm->page[pi].comp) { From f1bc386b319e93e56453ae27e9e83817bb1f6f95 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Wed, 29 Jun 2022 14:34:36 +0200 Subject: [PATCH 005/396] drm/vc4: hdmi: Depends on CONFIG_PM We already depend on runtime PM to get the power domains and clocks for most of the devices supported by the vc4 driver, so let's just select it to make sure it's there. Link: https://lore.kernel.org/r/20220629123510.1915022-38-maxime@cerno.tech Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> --- drivers/gpu/drm/vc4/Kconfig | 1 + drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index 061be9a6619d..b0f3117102ca 100644 --- a/drivers/gpu/drm/vc4/Kconfig +++ b/drivers/gpu/drm/vc4/Kconfig @@ -8,6 +8,7 @@ config DRM_VC4 depends on DRM depends on SND && SND_SOC depends on COMMON_CLK + depends on PM select DRM_DISPLAY_HDMI_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index e078f4ce0b4b..4a2e24421089 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2854,7 +2854,7 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return 0; } -static int __maybe_unused vc4_hdmi_runtime_suspend(struct device *dev) +static int vc4_hdmi_runtime_suspend(struct device *dev) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); From 53565c28e6af2cef6bbf438c34250135e3564459 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Wed, 29 Jun 2022 14:34:37 +0200 Subject: [PATCH 006/396] drm/vc4: hdmi: Rework power up The current code tries to handle the case where CONFIG_PM isn't selected by first calling our runtime_resume implementation and then properly report the power state to the runtime_pm core. This allows to have a functionning device even if pm_runtime_get_* functions are nops. However, the device power state if CONFIG_PM is enabled is RPM_SUSPENDED, and thus our vc4_hdmi_write() and vc4_hdmi_read() calls in the runtime_pm hooks will now report a warning since the device might not be properly powered. Even more so, we need CONFIG_PM enabled since the previous RaspberryPi have a power domain that needs to be powered up for the HDMI controller to be usable. The previous patch has created a dependency on CONFIG_PM, now we can just assume it's there and only call pm_runtime_resume_and_get() to make sure our device is powered in bind. Link: https://lore.kernel.org/r/20220629123510.1915022-39-maxime@cerno.tech Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> --- drivers/gpu/drm/vc4/vc4_hdmi.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4a2e24421089..e77bdc37b16f 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2971,18 +2971,16 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->disable_4kp60 = true; } - /* - * We need to have the device powered up at this point to call - * our reset hook and for the CEC init. - */ - ret = vc4_hdmi_runtime_resume(dev); - if (ret) - goto err_put_ddc; - - pm_runtime_get_noresume(dev); - pm_runtime_set_active(dev); pm_runtime_enable(dev); + /* + * We need to have the device powered up at this point to call + * our reset hook and for the CEC init. + */ + ret = pm_runtime_resume_and_get(dev); + if (ret) + goto err_disable_runtime_pm; + if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) { @@ -3027,6 +3025,7 @@ err_destroy_conn: err_destroy_encoder: drm_encoder_cleanup(encoder); pm_runtime_put_sync(dev); +err_disable_runtime_pm: pm_runtime_disable(dev); err_put_ddc: put_device(&vc4_hdmi->ddc->dev); From 9c442b7aabb3953d3bbd156dc68a16cec60d3bff Mon Sep 17 00:00:00 2001 From: Samuel Holland <samuel@sholland.org> Date: Sat, 2 Jul 2022 14:32:50 -0500 Subject: [PATCH 007/396] drm/sun4i: Update Kconfig defaults and descriptions Allwinner display drivers are split roughly into two generations. The first generation was found on early 32-bit ARM SoCs and contains DE1.0 and a custom HDMI controller. Clarify that these options only apply to a specific list of SoCs, and limit selecting them to 32-bit ARM, to avoid confusion. The second generation, found in A83T and newer SoCs (both 32-bit and 64-bit), contains a DE2.0 and a DesignWare HDMI controller. Since this is the most widely-used generation, enable it by default. The previous default condition (MACH_SUN8I) was limited to 32-bit SoCs. Also enable the DSI controller by default, which is found on 64-bit SoCs as well. Signed-off-by: Samuel Holland <samuel@sholland.org> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220702193250.52959-1-samuel@sholland.org --- drivers/gpu/drm/sun4i/Kconfig | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index 3a43c436c74a..1c2f8909f3cd 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig @@ -16,23 +16,25 @@ config DRM_SUN4I if DRM_SUN4I config DRM_SUN4I_HDMI - tristate "Allwinner A10 HDMI Controller Support" + tristate "Allwinner A10/A10s/A20/A31 HDMI Controller Support" + depends on ARM || COMPILE_TEST default DRM_SUN4I help - Choose this option if you have an Allwinner SoC with an HDMI - controller. + Choose this option if you have an Allwinner A10/A10s/A20/A31 + SoC with an HDMI controller. config DRM_SUN4I_HDMI_CEC - bool "Allwinner A10 HDMI CEC Support" + bool "Allwinner A10/A10s/A20/A31 HDMI CEC Support" depends on DRM_SUN4I_HDMI select CEC_CORE select CEC_PIN help - Choose this option if you have an Allwinner SoC with an HDMI - controller and want to use CEC. + Choose this option if you have an Allwinner A10/A10s/A20/A31 + SoC with an HDMI controller and want to use CEC. config DRM_SUN4I_BACKEND tristate "Support for Allwinner A10 Display Engine Backend" + depends on ARM || COMPILE_TEST default DRM_SUN4I help Choose this option if you have an Allwinner SoC with the @@ -41,8 +43,8 @@ config DRM_SUN4I_BACKEND selected the module will be called sun4i-backend. config DRM_SUN6I_DSI - tristate "Allwinner A31 MIPI-DSI Controller Support" - default MACH_SUN8I + tristate "Allwinner A31/A64 MIPI-DSI Controller Support" + default DRM_SUN4I select CRC_CCITT select DRM_MIPI_DSI select RESET_CONTROLLER @@ -55,15 +57,17 @@ config DRM_SUN6I_DSI config DRM_SUN8I_DW_HDMI tristate "Support for Allwinner version of DesignWare HDMI" depends on DRM_SUN4I + default DRM_SUN4I select DRM_DW_HDMI help Choose this option if you have an Allwinner SoC with the - DesignWare HDMI controller with custom HDMI PHY. If M is + DesignWare HDMI controller. SoCs that support HDMI and + have a Display Engine 2.0 contain this controller. If M is selected the module will be called sun8i_dw_hdmi. config DRM_SUN8I_MIXER tristate "Support for Allwinner Display Engine 2.0 Mixer" - default MACH_SUN8I + default DRM_SUN4I help Choose this option if you have an Allwinner SoC with the Allwinner Display Engine 2.0, which has a mixer to do some @@ -75,6 +79,6 @@ config DRM_SUN8I_TCON_TOP default DRM_SUN4I if DRM_SUN8I_MIXER!=n help TCON TOP is responsible for configuring display pipeline for - HTMI, TVE and LCD. + HDMI, TVE and LCD. endif From 7d1202738efda60155d98b370b3c70d336be0eea Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Mon, 4 Jul 2022 13:55:40 +0300 Subject: [PATCH 008/396] drm/bridge: Avoid uninitialized variable warning This code works, but technically it uses "num_in_bus_fmts" before it has been initialized so it leads to static checker warnings and probably KMEMsan warnings at run time. Initialize the variable to zero to silence the warning. Fixes: f32df58acc68 ("drm/bridge: Add the necessary bits to support bus format negotiation") Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/YrrIs3hoGcPVmXc5@kili --- drivers/gpu/drm/drm_bridge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 6abf7a2407e9..1545c50fd1c8 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -847,8 +847,8 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, struct drm_connector_state *conn_state, u32 out_bus_fmt) { + unsigned int i, num_in_bus_fmts = 0; struct drm_bridge_state *cur_state; - unsigned int num_in_bus_fmts, i; struct drm_bridge *prev_bridge; u32 *in_bus_fmts; int ret; @@ -969,7 +969,7 @@ drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge, struct drm_connector *conn = conn_state->connector; struct drm_encoder *encoder = bridge->encoder; struct drm_bridge_state *last_bridge_state; - unsigned int i, num_out_bus_fmts; + unsigned int i, num_out_bus_fmts = 0; struct drm_bridge *last_bridge; u32 *out_bus_fmts; int ret = 0; From d72ac4bbf4cc8f6b50526ce400861f176659884f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> Date: Fri, 8 Jul 2022 11:49:20 +0200 Subject: [PATCH 009/396] drm/panel: simple: Make panel_simple_remove() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit panel_simple_remove() returns zero unconditionally. Make it return no value instead making more obvious what happens in the callers. This is a preparation for making platform and mipi-dsi remove callbacks return void. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220708094922.1408248-2-u.kleine-koenig@pengutronix.de --- drivers/gpu/drm/panel/panel-simple.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index ff5e1a44c43a..0ad3d1de4a98 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -696,7 +696,7 @@ free_ddc: return err; } -static int panel_simple_remove(struct device *dev) +static void panel_simple_remove(struct device *dev) { struct panel_simple *panel = dev_get_drvdata(dev); @@ -708,8 +708,6 @@ static int panel_simple_remove(struct device *dev) pm_runtime_disable(dev); if (panel->ddc) put_device(&panel->ddc->dev); - - return 0; } static void panel_simple_shutdown(struct device *dev) @@ -4273,7 +4271,9 @@ static int panel_simple_platform_probe(struct platform_device *pdev) static int panel_simple_platform_remove(struct platform_device *pdev) { - return panel_simple_remove(&pdev->dev); + panel_simple_remove(&pdev->dev); + + return 0; } static void panel_simple_platform_shutdown(struct platform_device *pdev) @@ -4574,7 +4574,9 @@ static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi) if (err < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); - return panel_simple_remove(&dsi->dev); + panel_simple_remove(&dsi->dev); + + return 0; } static void panel_simple_dsi_shutdown(struct mipi_dsi_device *dsi) From 1fd452c403ca2cd9dcbd8465f9f72be52e15ac1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> Date: Fri, 8 Jul 2022 11:49:21 +0200 Subject: [PATCH 010/396] drm/panel-novatek-nt35510: Emit an error message if power off fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returning an error code from a mipi_dsi remove callback fails, this is silently ignored. (mipi_dsi_drv_remove() propagates the return value to device_remove() which ignores it.) So emit an error code in the driver remove function and return 0. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220708094922.1408248-3-u.kleine-koenig@pengutronix.de --- drivers/gpu/drm/panel/panel-novatek-nt35510.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index 40ea41b0a5dd..1b3e0154bfb8 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -974,9 +974,12 @@ static int nt35510_remove(struct mipi_dsi_device *dsi) mipi_dsi_detach(dsi); /* Power off */ ret = nt35510_power_off(nt); + if (ret) + dev_err(&dsi->dev, "Failed to power off\n"); + drm_panel_remove(&nt->panel); - return ret; + return 0; } /* From 79abca2b399009eb8d12c652d0f0f7a9c7a06289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> Date: Fri, 8 Jul 2022 11:49:22 +0200 Subject: [PATCH 011/396] drm/mipi-dsi: Make remove callback return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All implementations return 0 and the return value of mipi_dsi_drv_remove() is ignored anyhow. So change the prototype of the remove function to return no value. This way driver authors are not tempted to assume that passing an error to the upper layer is a good idea. All drivers are adapted accordingly. There is no intended change of behaviour. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220708094922.1408248-4-u.kleine-koenig@pengutronix.de --- drivers/gpu/drm/bridge/chipone-icn6211.c | 4 +--- drivers/gpu/drm/bridge/tc358762.c | 4 +--- drivers/gpu/drm/bridge/tc358764.c | 4 +--- drivers/gpu/drm/drm_mipi_dsi.c | 4 +++- drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c | 4 +--- drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c | 4 +--- drivers/gpu/drm/panel/panel-boe-himax8279d.c | 4 +--- drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 4 +--- drivers/gpu/drm/panel/panel-dsi-cm.c | 4 +--- drivers/gpu/drm/panel/panel-ebbg-ft8719.c | 4 +--- drivers/gpu/drm/panel/panel-elida-kd35t133.c | 4 +--- drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c | 4 +--- drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c | 4 +--- drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 4 +--- drivers/gpu/drm/panel/panel-innolux-p079zca.c | 4 +--- drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c | 4 +--- drivers/gpu/drm/panel/panel-jdi-lt070me05000.c | 4 +--- drivers/gpu/drm/panel/panel-khadas-ts050.c | 4 +--- drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c | 4 +--- drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c | 4 +--- drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c | 4 +--- drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 4 +--- drivers/gpu/drm/panel/panel-novatek-nt35510.c | 4 +--- drivers/gpu/drm/panel/panel-novatek-nt35560.c | 4 +--- drivers/gpu/drm/panel/panel-novatek-nt35950.c | 4 +--- drivers/gpu/drm/panel/panel-novatek-nt36672a.c | 4 +--- drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 4 +--- drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c | 4 +--- drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 4 +--- drivers/gpu/drm/panel/panel-raydium-rm67191.c | 4 +--- drivers/gpu/drm/panel/panel-raydium-rm68200.c | 4 +--- drivers/gpu/drm/panel/panel-ronbo-rb070d30.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c | 3 +-- drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-sofef00.c | 4 +--- drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 6 ++---- drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 4 +--- drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c | 4 +--- drivers/gpu/drm/panel/panel-simple.c | 4 +--- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 4 +--- drivers/gpu/drm/panel/panel-sitronix-st7703.c | 4 +--- drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c | 4 +--- drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c | 4 +--- drivers/gpu/drm/panel/panel-truly-nt35597.c | 3 +-- drivers/gpu/drm/panel/panel-visionox-rm69299.c | 3 +-- drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c | 4 +--- include/drm/drm_mipi_dsi.h | 2 +- 51 files changed, 54 insertions(+), 147 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 481c86b2406e..b07d2d16c3cf 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -735,14 +735,12 @@ static int chipone_i2c_probe(struct i2c_client *client, return chipone_dsi_host_attach(icn); } -static int chipone_dsi_remove(struct mipi_dsi_device *dsi) +static void chipone_dsi_remove(struct mipi_dsi_device *dsi) { struct chipone *icn = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_bridge_remove(&icn->bridge); - - return 0; } static const struct of_device_id chipone_of_match[] = { diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index 40439da4db49..7f4fce1aa998 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -241,14 +241,12 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) return ret; } -static int tc358762_remove(struct mipi_dsi_device *dsi) +static void tc358762_remove(struct mipi_dsi_device *dsi) { struct tc358762 *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_bridge_remove(&ctx->bridge); - - return 0; } static const struct of_device_id tc358762_of_match[] = { diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index fdfb14aca926..53259c12d777 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -381,14 +381,12 @@ static int tc358764_probe(struct mipi_dsi_device *dsi) return ret; } -static int tc358764_remove(struct mipi_dsi_device *dsi) +static void tc358764_remove(struct mipi_dsi_device *dsi) { struct tc358764 *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_bridge_remove(&ctx->bridge); - - return 0; } static const struct of_device_id tc358764_of_match[] = { diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index c40bde96cfdf..2e25804d6ffa 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -1236,7 +1236,9 @@ static int mipi_dsi_drv_remove(struct device *dev) struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); - return drv->remove(dsi); + drv->remove(dsi); + + return 0; } static void mipi_dsi_drv_shutdown(struct device *dev) diff --git a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c index 174ff434bd71..b3235781e6ba 100644 --- a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c +++ b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c @@ -321,7 +321,7 @@ static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi) return 0; } -static int tm5p5_nt35596_remove(struct mipi_dsi_device *dsi) +static void tm5p5_nt35596_remove(struct mipi_dsi_device *dsi) { struct tm5p5_nt35596 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -332,8 +332,6 @@ static int tm5p5_nt35596_remove(struct mipi_dsi_device *dsi) "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id tm5p5_nt35596_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c b/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c index ef00cd67dc40..ad58840eda41 100644 --- a/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c +++ b/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c @@ -410,7 +410,7 @@ static int boe_bf060y8m_aj0_probe(struct mipi_dsi_device *dsi) return 0; } -static int boe_bf060y8m_aj0_remove(struct mipi_dsi_device *dsi) +static void boe_bf060y8m_aj0_remove(struct mipi_dsi_device *dsi) { struct boe_bf060y8m_aj0 *boe = mipi_dsi_get_drvdata(dsi); int ret; @@ -420,8 +420,6 @@ static int boe_bf060y8m_aj0_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&boe->panel); - - return 0; } static const struct of_device_id boe_bf060y8m_aj0_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c index 42854bd37fd5..d879b3b14c48 100644 --- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c +++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c @@ -919,7 +919,7 @@ static int panel_probe(struct mipi_dsi_device *dsi) return err; } -static int panel_remove(struct mipi_dsi_device *dsi) +static void panel_remove(struct mipi_dsi_device *dsi) { struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi); int err; @@ -937,8 +937,6 @@ static int panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); drm_panel_remove(&pinfo->base); - - return 0; } static void panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index 07f722f33fc5..857a2f0420d7 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -1622,7 +1622,7 @@ static void boe_panel_shutdown(struct mipi_dsi_device *dsi) drm_panel_unprepare(&boe->base); } -static int boe_panel_remove(struct mipi_dsi_device *dsi) +static void boe_panel_remove(struct mipi_dsi_device *dsi) { struct boe_panel *boe = mipi_dsi_get_drvdata(dsi); int ret; @@ -1635,8 +1635,6 @@ static int boe_panel_remove(struct mipi_dsi_device *dsi) if (boe->base.dev) drm_panel_remove(&boe->base); - - return 0; } static const struct of_device_id boe_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c b/drivers/gpu/drm/panel/panel-dsi-cm.c index b0213a518f9d..ba17bcc4461c 100644 --- a/drivers/gpu/drm/panel/panel-dsi-cm.c +++ b/drivers/gpu/drm/panel/panel-dsi-cm.c @@ -579,7 +579,7 @@ err_bl: return r; } -static int dsicm_remove(struct mipi_dsi_device *dsi) +static void dsicm_remove(struct mipi_dsi_device *dsi) { struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi); @@ -593,8 +593,6 @@ static int dsicm_remove(struct mipi_dsi_device *dsi) if (ddata->extbldev) put_device(&ddata->extbldev->dev); - - return 0; } static const struct dsic_panel_data taal_data = { diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c index 386f8321b930..e85d63a176d0 100644 --- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c +++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c @@ -250,7 +250,7 @@ static int ebbg_ft8719_probe(struct mipi_dsi_device *dsi) return 0; } -static int ebbg_ft8719_remove(struct mipi_dsi_device *dsi) +static void ebbg_ft8719_remove(struct mipi_dsi_device *dsi) { struct ebbg_ft8719 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -260,8 +260,6 @@ static int ebbg_ft8719_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id ebbg_ft8719_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-elida-kd35t133.c b/drivers/gpu/drm/panel/panel-elida-kd35t133.c index 01dd555a7f26..eee714cf3f49 100644 --- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c +++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c @@ -321,7 +321,7 @@ static void kd35t133_shutdown(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } -static int kd35t133_remove(struct mipi_dsi_device *dsi) +static void kd35t133_remove(struct mipi_dsi_device *dsi) { struct kd35t133 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -333,8 +333,6 @@ static int kd35t133_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id kd35t133_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c index cb0bb3076099..76572c922983 100644 --- a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c +++ b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c @@ -486,14 +486,12 @@ static int k101_im2ba02_dsi_probe(struct mipi_dsi_device *dsi) return 0; } -static int k101_im2ba02_dsi_remove(struct mipi_dsi_device *dsi) +static void k101_im2ba02_dsi_remove(struct mipi_dsi_device *dsi) { struct k101_im2ba02 *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id k101_im2ba02_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c index ee61d60eceae..df493da50afe 100644 --- a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +++ b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c @@ -233,14 +233,12 @@ static int feiyang_dsi_probe(struct mipi_dsi_device *dsi) return 0; } -static int feiyang_dsi_remove(struct mipi_dsi_device *dsi) +static void feiyang_dsi_remove(struct mipi_dsi_device *dsi) { struct feiyang *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id feiyang_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index 596861269774..cbb68caa36f2 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -923,14 +923,12 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi) return mipi_dsi_attach(dsi); } -static int ili9881c_dsi_remove(struct mipi_dsi_device *dsi) +static void ili9881c_dsi_remove(struct mipi_dsi_device *dsi) { struct ili9881c *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct ili9881c_desc lhr050h41_desc = { diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c index f194b62e290c..9992d0d4c0e5 100644 --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c @@ -506,7 +506,7 @@ static int innolux_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int innolux_panel_remove(struct mipi_dsi_device *dsi) +static void innolux_panel_remove(struct mipi_dsi_device *dsi) { struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi); int err; @@ -524,8 +524,6 @@ static int innolux_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); innolux_panel_del(innolux); - - return 0; } static void innolux_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c index 31eafbc38ec0..d8765b2294fb 100644 --- a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c +++ b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c @@ -288,7 +288,7 @@ static int jdi_fhd_r63452_probe(struct mipi_dsi_device *dsi) return 0; } -static int jdi_fhd_r63452_remove(struct mipi_dsi_device *dsi) +static void jdi_fhd_r63452_remove(struct mipi_dsi_device *dsi) { struct jdi_fhd_r63452 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -298,8 +298,6 @@ static int jdi_fhd_r63452_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id jdi_fhd_r63452_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c index 3c86ad262d5e..8f4f137a2af6 100644 --- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c @@ -482,7 +482,7 @@ static int jdi_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int jdi_panel_remove(struct mipi_dsi_device *dsi) +static void jdi_panel_remove(struct mipi_dsi_device *dsi) { struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi); int ret; @@ -497,8 +497,6 @@ static int jdi_panel_remove(struct mipi_dsi_device *dsi) ret); jdi_panel_del(jdi); - - return 0; } static void jdi_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c b/drivers/gpu/drm/panel/panel-khadas-ts050.c index a3ec4cbdbf7a..1ab1ebe30882 100644 --- a/drivers/gpu/drm/panel/panel-khadas-ts050.c +++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c @@ -830,7 +830,7 @@ static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi) return err; } -static int khadas_ts050_panel_remove(struct mipi_dsi_device *dsi) +static void khadas_ts050_panel_remove(struct mipi_dsi_device *dsi) { struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi); int err; @@ -842,8 +842,6 @@ static int khadas_ts050_panel_remove(struct mipi_dsi_device *dsi) drm_panel_remove(&khadas_ts050->base); drm_panel_disable(&khadas_ts050->base); drm_panel_unprepare(&khadas_ts050->base); - - return 0; } static void khadas_ts050_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c index daccb1fd5fda..17f8d80cf2b3 100644 --- a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c @@ -415,7 +415,7 @@ static int kingdisplay_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int kingdisplay_panel_remove(struct mipi_dsi_device *dsi) +static void kingdisplay_panel_remove(struct mipi_dsi_device *dsi) { struct kingdisplay_panel *kingdisplay = mipi_dsi_get_drvdata(dsi); int err; @@ -433,8 +433,6 @@ static int kingdisplay_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); kingdisplay_panel_del(kingdisplay); - - return 0; } static void kingdisplay_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c index a5a414920430..5619f186d28c 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c @@ -628,7 +628,7 @@ static void ltk050h3146w_shutdown(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } -static int ltk050h3146w_remove(struct mipi_dsi_device *dsi) +static void ltk050h3146w_remove(struct mipi_dsi_device *dsi) { struct ltk050h3146w *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -640,8 +640,6 @@ static int ltk050h3146w_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id ltk050h3146w_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c index 21e48923836d..39e408c9f762 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c @@ -477,7 +477,7 @@ static void ltk500hd1829_shutdown(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } -static int ltk500hd1829_remove(struct mipi_dsi_device *dsi) +static void ltk500hd1829_remove(struct mipi_dsi_device *dsi) { struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -489,8 +489,6 @@ static int ltk500hd1829_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id ltk500hd1829_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c index 31daae1da9c9..772e3b6acece 100644 --- a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c +++ b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c @@ -336,7 +336,7 @@ static void mantix_shutdown(struct mipi_dsi_device *dsi) drm_panel_disable(&ctx->panel); } -static int mantix_remove(struct mipi_dsi_device *dsi) +static void mantix_remove(struct mipi_dsi_device *dsi) { struct mantix *ctx = mipi_dsi_get_drvdata(dsi); @@ -344,8 +344,6 @@ static int mantix_remove(struct mipi_dsi_device *dsi) mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id mantix_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index 1b3e0154bfb8..c613ad967ba6 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -966,7 +966,7 @@ static int nt35510_probe(struct mipi_dsi_device *dsi) return 0; } -static int nt35510_remove(struct mipi_dsi_device *dsi) +static void nt35510_remove(struct mipi_dsi_device *dsi) { struct nt35510 *nt = mipi_dsi_get_drvdata(dsi); int ret; @@ -978,8 +978,6 @@ static int nt35510_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to power off\n"); drm_panel_remove(&nt->panel); - - return 0; } /* diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35560.c b/drivers/gpu/drm/panel/panel-novatek-nt35560.c index 1b6042321ea1..cc7f96d70826 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35560.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35560.c @@ -523,14 +523,12 @@ static int nt35560_probe(struct mipi_dsi_device *dsi) return 0; } -static int nt35560_remove(struct mipi_dsi_device *dsi) +static void nt35560_remove(struct mipi_dsi_device *dsi) { struct nt35560 *nt = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&nt->panel); - - return 0; } static const struct of_device_id nt35560_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35950.c b/drivers/gpu/drm/panel/panel-novatek-nt35950.c index 288c7fa83ecc..3a844917da07 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35950.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35950.c @@ -620,7 +620,7 @@ static int nt35950_probe(struct mipi_dsi_device *dsi) return 0; } -static int nt35950_remove(struct mipi_dsi_device *dsi) +static void nt35950_remove(struct mipi_dsi_device *dsi) { struct nt35950 *nt = mipi_dsi_get_drvdata(dsi); int ret; @@ -639,8 +639,6 @@ static int nt35950_remove(struct mipi_dsi_device *dsi) } drm_panel_remove(&nt->panel); - - return 0; } static const struct nt35950_panel_mode sharp_ls055d1sx04_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c index 6d6ce42787e2..73bcffa1e0c1 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c @@ -669,7 +669,7 @@ static int nt36672a_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int nt36672a_panel_remove(struct mipi_dsi_device *dsi) +static void nt36672a_panel_remove(struct mipi_dsi_device *dsi) { struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi); int err; @@ -687,8 +687,6 @@ static int nt36672a_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); drm_panel_remove(&pinfo->base); - - return 0; } static void nt36672a_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c index dfb43b1374e7..b4729a94c34a 100644 --- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c +++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c @@ -497,14 +497,12 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi) return 0; } -static int otm8009a_remove(struct mipi_dsi_device *dsi) +static void otm8009a_remove(struct mipi_dsi_device *dsi) { struct otm8009a *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id orisetech_otm8009a_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c index 198493a6eb6a..493e0504f6f7 100644 --- a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c +++ b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c @@ -206,7 +206,7 @@ static int osd101t2587_panel_probe(struct mipi_dsi_device *dsi) return ret; } -static int osd101t2587_panel_remove(struct mipi_dsi_device *dsi) +static void osd101t2587_panel_remove(struct mipi_dsi_device *dsi) { struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi); int ret; @@ -221,8 +221,6 @@ static int osd101t2587_panel_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); - - return ret; } static void osd101t2587_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c index 3991f5d950af..8ba6d8287938 100644 --- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c +++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c @@ -250,7 +250,7 @@ static int wuxga_nt_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) +static void wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) { struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi); int ret; @@ -264,8 +264,6 @@ static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); wuxga_nt_panel_del(wuxga_nt); - - return 0; } static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c index 4e021a572211..dbb1ed4efbed 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c @@ -616,7 +616,7 @@ static int rad_panel_probe(struct mipi_dsi_device *dsi) return ret; } -static int rad_panel_remove(struct mipi_dsi_device *dsi) +static void rad_panel_remove(struct mipi_dsi_device *dsi) { struct rad_panel *rad = mipi_dsi_get_drvdata(dsi); struct device *dev = &dsi->dev; @@ -627,8 +627,6 @@ static int rad_panel_remove(struct mipi_dsi_device *dsi) dev_err(dev, "Failed to detach from host (%d)\n", ret); drm_panel_remove(&rad->panel); - - return 0; } static void rad_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-raydium-rm68200.c b/drivers/gpu/drm/panel/panel-raydium-rm68200.c index 412c0dbcb2b6..5f9b340588fb 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm68200.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm68200.c @@ -412,14 +412,12 @@ static int rm68200_probe(struct mipi_dsi_device *dsi) return 0; } -static int rm68200_remove(struct mipi_dsi_device *dsi) +static void rm68200_remove(struct mipi_dsi_device *dsi) { struct rm68200 *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id raydium_rm68200_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c index 1fb579a574d9..a8a98c91b13c 100644 --- a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c +++ b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c @@ -208,14 +208,12 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi) return 0; } -static int rb070d30_panel_dsi_remove(struct mipi_dsi_device *dsi) +static void rb070d30_panel_dsi_remove(struct mipi_dsi_device *dsi) { struct rb070d30_panel *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id rb070d30_panel_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c index 70560cac53a9..008e2b0d6652 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c @@ -212,14 +212,12 @@ static int s6d16d0_probe(struct mipi_dsi_device *dsi) return ret; } -static int s6d16d0_remove(struct mipi_dsi_device *dsi) +static void s6d16d0_remove(struct mipi_dsi_device *dsi) { struct s6d16d0 *s6 = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&s6->panel); - - return 0; } static const struct of_device_id s6d16d0_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c index 0ab1b7ec84cd..5c621b15e84c 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c @@ -747,15 +747,13 @@ remove_panel: return ret; } -static int s6e3ha2_remove(struct mipi_dsi_device *dsi) +static void s6e3ha2_remove(struct mipi_dsi_device *dsi) { struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); backlight_device_unregister(ctx->bl_dev); - - return 0; } static const struct of_device_id s6e3ha2_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c index e38262b67ff7..e06fd35de814 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c @@ -488,7 +488,7 @@ remove_panel: return ret; } -static int s6e63j0x03_remove(struct mipi_dsi_device *dsi) +static void s6e63j0x03_remove(struct mipi_dsi_device *dsi) { struct s6e63j0x03 *ctx = mipi_dsi_get_drvdata(dsi); @@ -496,8 +496,6 @@ static int s6e63j0x03_remove(struct mipi_dsi_device *dsi) drm_panel_remove(&ctx->panel); backlight_device_unregister(ctx->bl_dev); - - return 0; } static const struct of_device_id s6e63j0x03_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c index e0f773678168..ed3895e4ca5e 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c @@ -113,11 +113,10 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi) return ret; } -static int s6e63m0_dsi_remove(struct mipi_dsi_device *dsi) +static void s6e63m0_dsi_remove(struct mipi_dsi_device *dsi) { mipi_dsi_detach(dsi); s6e63m0_remove(&dsi->dev); - return 0; } static const struct of_device_id s6e63m0_dsi_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c index 29fde3823212..97ff7a18545c 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c @@ -254,7 +254,7 @@ static int s6e88a0_ams452ef01_probe(struct mipi_dsi_device *dsi) return 0; } -static int s6e88a0_ams452ef01_remove(struct mipi_dsi_device *dsi) +static void s6e88a0_ams452ef01_remove(struct mipi_dsi_device *dsi) { struct s6e88a0_ams452ef01 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -264,8 +264,6 @@ static int s6e88a0_ams452ef01_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id s6e88a0_ams452ef01_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c index 9b3599d6d2de..54213beafaf5 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c @@ -1028,14 +1028,12 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi) return ret; } -static int s6e8aa0_remove(struct mipi_dsi_device *dsi) +static void s6e8aa0_remove(struct mipi_dsi_device *dsi) { struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id s6e8aa0_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-sofef00.c b/drivers/gpu/drm/panel/panel-samsung-sofef00.c index 1fb37fda4ba9..1a0d24595faa 100644 --- a/drivers/gpu/drm/panel/panel-samsung-sofef00.c +++ b/drivers/gpu/drm/panel/panel-samsung-sofef00.c @@ -305,7 +305,7 @@ static int sofef00_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int sofef00_panel_remove(struct mipi_dsi_device *dsi) +static void sofef00_panel_remove(struct mipi_dsi_device *dsi) { struct sofef00_panel *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -315,8 +315,6 @@ static int sofef00_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id sofef00_panel_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c index f8cd2a42ed13..14851408a5e1 100644 --- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c @@ -391,7 +391,7 @@ static int sharp_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int sharp_panel_remove(struct mipi_dsi_device *dsi) +static void sharp_panel_remove(struct mipi_dsi_device *dsi) { struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi); int err; @@ -399,7 +399,7 @@ static int sharp_panel_remove(struct mipi_dsi_device *dsi) /* only detach from host for the DSI-LINK2 interface */ if (!sharp) { mipi_dsi_detach(dsi); - return 0; + return; } err = drm_panel_disable(&sharp->base); @@ -411,8 +411,6 @@ static int sharp_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); sharp_panel_del(sharp); - - return 0; } static void sharp_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c index 25829a0a8e80..d1ec80a3e3c7 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c @@ -305,7 +305,7 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) return 0; } -static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi) +static void sharp_nt_panel_remove(struct mipi_dsi_device *dsi) { struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi); int ret; @@ -319,8 +319,6 @@ static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); sharp_nt_panel_del(sharp_nt); - - return 0; } static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c index e12570561629..8a4e0c1fe73f 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c @@ -298,7 +298,7 @@ static int sharp_ls060_probe(struct mipi_dsi_device *dsi) return 0; } -static int sharp_ls060_remove(struct mipi_dsi_device *dsi) +static void sharp_ls060_remove(struct mipi_dsi_device *dsi) { struct sharp_ls060 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -308,8 +308,6 @@ static int sharp_ls060_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id sharp_ls060t1sx01_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 0ad3d1de4a98..c1d224cb719d 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -4566,7 +4566,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) return err; } -static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi) +static void panel_simple_dsi_remove(struct mipi_dsi_device *dsi) { int err; @@ -4575,8 +4575,6 @@ static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); panel_simple_remove(&dsi->dev); - - return 0; } static void panel_simple_dsi_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 320a2a8fd459..5192d9aa572a 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -387,14 +387,12 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) return mipi_dsi_attach(dsi); } -static int st7701_dsi_remove(struct mipi_dsi_device *dsi) +static void st7701_dsi_remove(struct mipi_dsi_device *dsi) { struct st7701 *st7701 = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(dsi); drm_panel_remove(&st7701->panel); - - return 0; } static const struct of_device_id st7701_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c index 73f69c929a75..86a472b01360 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c @@ -598,7 +598,7 @@ static void st7703_shutdown(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } -static int st7703_remove(struct mipi_dsi_device *dsi) +static void st7703_remove(struct mipi_dsi_device *dsi) { struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -612,8 +612,6 @@ static int st7703_remove(struct mipi_dsi_device *dsi) drm_panel_remove(&ctx->panel); st7703_debugfs_remove(ctx); - - return 0; } static const struct of_device_id st7703_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c b/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c index 69f07b15fca4..fa9be3c299c0 100644 --- a/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c +++ b/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c @@ -517,7 +517,7 @@ static int truly_nt35521_probe(struct mipi_dsi_device *dsi) return 0; } -static int truly_nt35521_remove(struct mipi_dsi_device *dsi) +static void truly_nt35521_remove(struct mipi_dsi_device *dsi) { struct truly_nt35521 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -527,8 +527,6 @@ static int truly_nt35521_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id truly_nt35521_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c index 820731be7147..d8487bc6d611 100644 --- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c +++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c @@ -210,7 +210,7 @@ static int tdo_tl070wsh30_panel_probe(struct mipi_dsi_device *dsi) return mipi_dsi_attach(dsi); } -static int tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi) +static void tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi) { struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = mipi_dsi_get_drvdata(dsi); int err; @@ -222,8 +222,6 @@ static int tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi) drm_panel_remove(&tdo_tl070wsh30->base); drm_panel_disable(&tdo_tl070wsh30->base); drm_panel_unprepare(&tdo_tl070wsh30->base); - - return 0; } static void tdo_tl070wsh30_panel_shutdown(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-truly-nt35597.c b/drivers/gpu/drm/panel/panel-truly-nt35597.c index 9ca5c7ff41d6..b31cffb660a7 100644 --- a/drivers/gpu/drm/panel/panel-truly-nt35597.c +++ b/drivers/gpu/drm/panel/panel-truly-nt35597.c @@ -616,7 +616,7 @@ err_panel_add: return ret; } -static int truly_nt35597_remove(struct mipi_dsi_device *dsi) +static void truly_nt35597_remove(struct mipi_dsi_device *dsi) { struct truly_nt35597 *ctx = mipi_dsi_get_drvdata(dsi); @@ -628,7 +628,6 @@ static int truly_nt35597_remove(struct mipi_dsi_device *dsi) } drm_panel_remove(&ctx->panel); - return 0; } static const struct of_device_id truly_nt35597_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-visionox-rm69299.c b/drivers/gpu/drm/panel/panel-visionox-rm69299.c index db2443ac81d3..ec228c269146 100644 --- a/drivers/gpu/drm/panel/panel-visionox-rm69299.c +++ b/drivers/gpu/drm/panel/panel-visionox-rm69299.c @@ -256,7 +256,7 @@ err_dsi_attach: return ret; } -static int visionox_rm69299_remove(struct mipi_dsi_device *dsi) +static void visionox_rm69299_remove(struct mipi_dsi_device *dsi) { struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi); @@ -264,7 +264,6 @@ static int visionox_rm69299_remove(struct mipi_dsi_device *dsi) mipi_dsi_device_unregister(ctx->dsi); drm_panel_remove(&ctx->panel); - return 0; } static const struct of_device_id visionox_rm69299_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c index 8177f5a360fb..2c54733ee241 100644 --- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c +++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c @@ -339,7 +339,7 @@ static void xpp055c272_shutdown(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } -static int xpp055c272_remove(struct mipi_dsi_device *dsi) +static void xpp055c272_remove(struct mipi_dsi_device *dsi) { struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi); int ret; @@ -351,8 +351,6 @@ static int xpp055c272_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id xpp055c272_of_match[] = { diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 91a164bdd8f3..53e3a8a2f241 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -322,7 +322,7 @@ int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, struct mipi_dsi_driver { struct device_driver driver; int(*probe)(struct mipi_dsi_device *dsi); - int(*remove)(struct mipi_dsi_device *dsi); + void (*remove)(struct mipi_dsi_device *dsi); void (*shutdown)(struct mipi_dsi_device *dsi); }; From 96dc635d5538055cb6ccd7b6e9290dfcfc385f97 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:46 +0200 Subject: [PATCH 012/396] drm/fourcc: Add drm_format_info_bpp() helper Add a helper to retrieve the actual number of bits per pixel for a plane, taking into account the number of characters and pixels per block for tiled formats. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/1cae5ebc28513ec1c91c66b00647ce3ca23bfba7.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_fourcc.c | 19 +++++++++++++++++++ include/drm/drm_fourcc.h | 1 + 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 07741b678798..cf48ea0b2cb7 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -370,6 +370,25 @@ unsigned int drm_format_info_block_height(const struct drm_format_info *info, } EXPORT_SYMBOL(drm_format_info_block_height); +/** + * drm_format_info_bpp - number of bits per pixel + * @info: pixel format info + * @plane: plane index + * + * Returns: + * The actual number of bits per pixel, depending on the plane index. + */ +unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane) +{ + if (!info || plane < 0 || plane >= info->num_planes) + return 0; + + return info->char_per_block[plane] * 8 / + (drm_format_info_block_width(info, plane) * + drm_format_info_block_height(info, plane)); +} +EXPORT_SYMBOL(drm_format_info_bpp); + /** * drm_format_info_min_pitch - computes the minimum required pitch in bytes * @info: pixel format info diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 22aa64d07c79..3800a7ad7f0c 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -313,6 +313,7 @@ unsigned int drm_format_info_block_width(const struct drm_format_info *info, int plane); unsigned int drm_format_info_block_height(const struct drm_format_info *info, int plane); +unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane); uint64_t drm_format_info_min_pitch(const struct drm_format_info *info, int plane, unsigned int buffer_width); From dc1dc76bd9a48c6aba3efae5eadb9a884043966e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:47 +0200 Subject: [PATCH 013/396] drm/fourcc: Add drm_format_info.is_color_indexed flag Add a flag to struct drm_format_info to indicate if a format is color-indexed, similar to the existing .is_yuv flag. This way generic code and drivers can just check this flag, instead of checking against a list of fourcc formats. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/90cd390b2b4d481661f966de7b504f1702d80dfd.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_fourcc.c | 2 +- include/drm/drm_fourcc.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index cf48ea0b2cb7..6c76bd821d17 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -132,7 +132,7 @@ EXPORT_SYMBOL(drm_driver_legacy_fb_format); const struct drm_format_info *__drm_format_info(u32 format) { static const struct drm_format_info formats[] = { - { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, { .format = DRM_FORMAT_R8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R10, .depth = 10, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R12, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 3800a7ad7f0c..532ae78ca747 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -138,6 +138,9 @@ struct drm_format_info { /** @is_yuv: Is it a YUV format? */ bool is_yuv; + + /** @is_color_indexed: Is it a color-indexed format? */ + bool is_color_indexed; }; /** From 356d2c8e76ebb1134a0685ce4b923d8201337475 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:48 +0200 Subject: [PATCH 014/396] drm/client: Use actual bpp when allocating frame buffers When allocating a frame buffer, the number of bits per pixel needed is derived from the deprecated drm_format_info.cpp[] field. While this may work for formats using less than 8 bits per pixel, it does lead to a large overallocation. Reduce memory consumption by using the actual number of bits per pixel instead. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/eabcf4f298184dabe46823fcf5ceffa1da0ec7ef.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index af3b7395bf69..2b230b4d6942 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -264,7 +264,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u dumb_args.width = width; dumb_args.height = height; - dumb_args.bpp = info->cpp[0] * 8; + dumb_args.bpp = drm_format_info_bpp(info, 0); ret = drm_mode_create_dumb(dev, &dumb_args, client->file); if (ret) goto err_delete; @@ -373,7 +373,7 @@ static int drm_client_buffer_addfb(struct drm_client_buffer *buffer, int ret; info = drm_format_info(format); - fb_req.bpp = info->cpp[0] * 8; + fb_req.bpp = drm_format_info_bpp(info, 0); fb_req.depth = info->depth; fb_req.width = width; fb_req.height = height; From 4c59b0805e9bf873fd3f5dca4fc53d8c220e39b4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:49 +0200 Subject: [PATCH 015/396] drm/framebuffer: Use actual bpp for DRM_IOCTL_MODE_GETFB When userspace queries the properties of a frame buffer, the number of bits per pixel is derived from the deprecated drm_format_info.cpp[] field, which does not take into account block sizes. Fix this by using the actual number of bits per pixel instead. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/b612780feef200b7f914a674db28ed227e7cdc64.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_framebuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 4562a8b86579..9899bf1485b2 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -530,7 +530,7 @@ int drm_mode_getfb(struct drm_device *dev, r->height = fb->height; r->width = fb->width; r->depth = fb->format->depth; - r->bpp = fb->format->cpp[0] * 8; + r->bpp = drm_format_info_bpp(fb->format, 0); r->pitch = fb->pitches[0]; /* GET_FB() is an unprivileged ioctl so we must not return a From e5bd7e3e4a68f0befe53f59954b25eec9a792d60 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:50 +0200 Subject: [PATCH 016/396] drm/fourcc: Add DRM_FORMAT_C[124] Introduce fourcc codes for color-indexed frame buffer formats with two, four, and sixteen colors, and provide a mapping from bits per pixel and depth to fourcc codes. As the number of bits per pixel is less than eight, these rely on proper block handling for the calculation of bits per pixel and pitch. The fill order (the order in which multiple pixels are packed in a byte) is the same order as used for indexed-color (2, 4, and 16 colors) images in the PNG specification, Version 1.2. This order is also the recommended and default order (FillOrder = 1) for palette-color (16 colors) images in the TIFF 6.0 Specification, and is also used for 16-color Linux frame buffer logos. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/3d88ca7ad32ff3ff3469c10f0b36c312ea233a33.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_fourcc.c | 21 +++++++++++++++++++++ include/uapi/drm/drm_fourcc.h | 3 +++ 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 6c76bd821d17..29f4fe199c4d 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -43,6 +43,21 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) uint32_t fmt = DRM_FORMAT_INVALID; switch (bpp) { + case 1: + if (depth == 1) + fmt = DRM_FORMAT_C1; + break; + + case 2: + if (depth == 2) + fmt = DRM_FORMAT_C2; + break; + + case 4: + if (depth == 4) + fmt = DRM_FORMAT_C4; + break; + case 8: if (depth == 8) fmt = DRM_FORMAT_C8; @@ -132,6 +147,12 @@ EXPORT_SYMBOL(drm_driver_legacy_fb_format); const struct drm_format_info *__drm_format_info(u32 format) { static const struct drm_format_info formats[] = { + { .format = DRM_FORMAT_C1, .depth = 1, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, + { .format = DRM_FORMAT_C2, .depth = 2, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, + { .format = DRM_FORMAT_C4, .depth = 4, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, { .format = DRM_FORMAT_R8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R10, .depth = 10, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index c1b4cfda7507..b9c746c3ebbc 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -99,6 +99,9 @@ extern "C" { #define DRM_FORMAT_INVALID 0 /* color index */ +#define DRM_FORMAT_C1 fourcc_code('C', '1', ' ', ' ') /* [7:0] C0:C1:C2:C3:C4:C5:C6:C7 1:1:1:1:1:1:1:1 eight pixels/byte */ +#define DRM_FORMAT_C2 fourcc_code('C', '2', ' ', ' ') /* [7:0] C0:C1:C2:C3 2:2:2:2 four pixels/byte */ +#define DRM_FORMAT_C4 fourcc_code('C', '4', ' ', ' ') /* [7:0] C0:C1 4:4 two pixels/byte */ #define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ /* 8 bpp Red */ From ba71593217b5b03c9e3385b268ff8613a71fc6ce Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:51 +0200 Subject: [PATCH 017/396] drm/fb-helper: Add support for DRM_FORMAT_C[124] Add support for color-indexed frame buffer formats with two, four, and sixteen colors to the DRM framebuffer helper functions: 1. Add support for 1, 2, and 4 bits per pixel to the damage helper, 2. For color-indexed modes, the length of the color bitfields must be set to the color depth, else the logo code may pick a logo with too many colors. Drop the incorrect DAC width comment, which originates from the i915 driver. 3. Accept C[124] modes when validating or filling in struct fb_var_screeninfo, and use the correct number of bits per pixel. 4. Set the visual to FB_VISUAL_PSEUDOCOLOR for all color-indexed modes. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/db3e80b445df661ff0cd7e698507a8d24a4c867e.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_fb_helper.c | 101 ++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 2d4cee6a10ff..71edb80fe0fb 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -377,12 +377,31 @@ static void drm_fb_helper_damage_blit_real(struct drm_fb_helper *fb_helper, struct iosys_map *dst) { struct drm_framebuffer *fb = fb_helper->fb; - unsigned int cpp = fb->format->cpp[0]; - size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp; - void *src = fb_helper->fbdev->screen_buffer + offset; - size_t len = (clip->x2 - clip->x1) * cpp; + size_t offset = clip->y1 * fb->pitches[0]; + size_t len = clip->x2 - clip->x1; unsigned int y; + void *src; + switch (drm_format_info_bpp(fb->format, 0)) { + case 1: + offset += clip->x1 / 8; + len = DIV_ROUND_UP(len + clip->x1 % 8, 8); + break; + case 2: + offset += clip->x1 / 4; + len = DIV_ROUND_UP(len + clip->x1 % 4, 4); + break; + case 4: + offset += clip->x1 / 2; + len = DIV_ROUND_UP(len + clip->x1 % 2, 2); + break; + default: + offset += clip->x1 * fb->format->cpp[0]; + len *= fb->format->cpp[0]; + break; + } + + src = fb_helper->fbdev->screen_buffer + offset; iosys_map_incr(dst, offset); /* go to first pixel within clip rect */ for (y = clip->y1; y < clip->y2; y++) { @@ -1274,19 +1293,23 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1, } static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, - u8 depth) + const struct drm_format_info *format) { - switch (depth) { - case 8: + u8 depth = format->depth; + + if (format->is_color_indexed) { var->red.offset = 0; var->green.offset = 0; var->blue.offset = 0; - var->red.length = 8; /* 8bit DAC */ - var->green.length = 8; - var->blue.length = 8; + var->red.length = depth; + var->green.length = depth; + var->blue.length = depth; var->transp.offset = 0; var->transp.length = 0; - break; + return; + } + + switch (depth) { case 15: var->red.offset = 10; var->green.offset = 5; @@ -1341,7 +1364,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, { struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; + const struct drm_format_info *format = fb->format; struct drm_device *dev = fb_helper->dev; + unsigned int bpp; if (in_dbg_master()) return -EINVAL; @@ -1351,22 +1376,33 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, var->pixclock = 0; } - if ((drm_format_info_block_width(fb->format, 0) > 1) || - (drm_format_info_block_height(fb->format, 0) > 1)) - return -EINVAL; + switch (format->format) { + case DRM_FORMAT_C1: + case DRM_FORMAT_C2: + case DRM_FORMAT_C4: + /* supported format with sub-byte pixels */ + break; + + default: + if ((drm_format_info_block_width(format, 0) > 1) || + (drm_format_info_block_height(format, 0) > 1)) + return -EINVAL; + break; + } /* * Changes struct fb_var_screeninfo are currently not pushed back * to KMS, hence fail if different settings are requested. */ - if (var->bits_per_pixel > fb->format->cpp[0] * 8 || + bpp = drm_format_info_bpp(format, 0); + if (var->bits_per_pixel > bpp || var->xres > fb->width || var->yres > fb->height || var->xres_virtual > fb->width || var->yres_virtual > fb->height) { drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb " "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, var->xres_virtual, var->yres_virtual, - fb->width, fb->height, fb->format->cpp[0] * 8); + fb->width, fb->height, bpp); return -EINVAL; } @@ -1381,13 +1417,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, !var->blue.length && !var->transp.length && !var->red.msb_right && !var->green.msb_right && !var->blue.msb_right && !var->transp.msb_right) { - drm_fb_helper_fill_pixel_fmt(var, fb->format->depth); + drm_fb_helper_fill_pixel_fmt(var, format); } /* * Likewise, bits_per_pixel should be rounded up to a supported value. */ - var->bits_per_pixel = fb->format->cpp[0] * 8; + var->bits_per_pixel = bpp; /* * drm fbdev emulation doesn't support changing the pixel format at all, @@ -1723,11 +1759,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, } static void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, - uint32_t depth) + bool is_color_indexed) { info->fix.type = FB_TYPE_PACKED_PIXELS; - info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : - FB_VISUAL_TRUECOLOR; + info->fix.visual = is_color_indexed ? FB_VISUAL_PSEUDOCOLOR + : FB_VISUAL_TRUECOLOR; info->fix.mmio_start = 0; info->fix.mmio_len = 0; info->fix.type_aux = 0; @@ -1744,19 +1780,31 @@ static void drm_fb_helper_fill_var(struct fb_info *info, uint32_t fb_width, uint32_t fb_height) { struct drm_framebuffer *fb = fb_helper->fb; + const struct drm_format_info *format = fb->format; + + switch (format->format) { + case DRM_FORMAT_C1: + case DRM_FORMAT_C2: + case DRM_FORMAT_C4: + /* supported format with sub-byte pixels */ + break; + + default: + WARN_ON((drm_format_info_block_width(format, 0) > 1) || + (drm_format_info_block_height(format, 0) > 1)); + break; + } - WARN_ON((drm_format_info_block_width(fb->format, 0) > 1) || - (drm_format_info_block_height(fb->format, 0) > 1)); info->pseudo_palette = fb_helper->pseudo_palette; info->var.xres_virtual = fb->width; info->var.yres_virtual = fb->height; - info->var.bits_per_pixel = fb->format->cpp[0] * 8; + info->var.bits_per_pixel = drm_format_info_bpp(format, 0); info->var.accel_flags = FB_ACCELF_TEXT; info->var.xoffset = 0; info->var.yoffset = 0; info->var.activate = FB_ACTIVATE_NOW; - drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth); + drm_fb_helper_fill_pixel_fmt(&info->var, format); info->var.xres = fb_width; info->var.yres = fb_height; @@ -1781,7 +1829,8 @@ void drm_fb_helper_fill_info(struct fb_info *info, { struct drm_framebuffer *fb = fb_helper->fb; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], + fb->format->is_color_indexed); drm_fb_helper_fill_var(info, fb_helper, sizes->fb_width, sizes->fb_height); From 0a2486f85e0cfa6439116abb9078ab888a619746 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:52 +0200 Subject: [PATCH 018/396] drm/gem-fb-helper: Use actual bpp for size calculations The AFBC helpers derive the number of bits per pixel from the deprecated drm_format_info.cpp[] field, which does not take into account block sizes. Fix this by using the actual number of bits per pixel instead. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/b1d938d903157627c4ac101df92a1f3bf8ebe83d.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_gem_framebuffer_helper.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 61339a9cd010..880a4975507f 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -490,6 +490,8 @@ void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_directi } EXPORT_SYMBOL(drm_gem_fb_end_cpu_access); +// TODO Drop this function and replace by drm_format_info_bpp() once all +// DRM_FORMAT_* provide proper block info in drivers/gpu/drm/drm_fourcc.c static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd) { @@ -497,11 +499,6 @@ static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev, info = drm_get_format_info(dev, mode_cmd); - /* use whatever a driver has set */ - if (info->cpp[0]) - return info->cpp[0] * 8; - - /* guess otherwise */ switch (info->format) { case DRM_FORMAT_YUV420_8BIT: return 12; @@ -510,11 +507,8 @@ static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev, case DRM_FORMAT_VUY101010: return 30; default: - break; + return drm_format_info_bpp(info, 0); } - - /* all attempts failed */ - return 0; } static int drm_gem_afbc_min_size(struct drm_device *dev, From 8aba4d30520ed656065eb36f0628109bdea385ee Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:53 +0200 Subject: [PATCH 019/396] drm/fourcc: Clarify the meaning of single-channel "red" Traditionally, the first channel has been called the "red" channel, but the fourcc values for single-channel "red" formats can also be used for other single-channel formats with a direct relationship between channel value and brightness, like grayscale. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/31d1792f26707a7270347e9916b4103470d2b192.1657294931.git.geert@linux-m68k.org --- include/uapi/drm/drm_fourcc.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index b9c746c3ebbc..9521057701c4 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -104,16 +104,16 @@ extern "C" { #define DRM_FORMAT_C4 fourcc_code('C', '4', ' ', ' ') /* [7:0] C0:C1 4:4 two pixels/byte */ #define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ -/* 8 bpp Red */ +/* 8 bpp Red (direct relationship between channel value and brightness) */ #define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ -/* 10 bpp Red */ +/* 10 bpp Red (direct relationship between channel value and brightness) */ #define DRM_FORMAT_R10 fourcc_code('R', '1', '0', ' ') /* [15:0] x:R 6:10 little endian */ -/* 12 bpp Red */ +/* 12 bpp Red (direct relationship between channel value and brightness) */ #define DRM_FORMAT_R12 fourcc_code('R', '1', '2', ' ') /* [15:0] x:R 4:12 little endian */ -/* 16 bpp Red */ +/* 16 bpp Red (direct relationship between channel value and brightness) */ #define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ /* 16 bpp RG */ From d093100b425df6fe400881f2e62c3f0be7bf18cf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:54 +0200 Subject: [PATCH 020/396] drm/fourcc: Add DRM_FORMAT_R[124] Introduce fourcc codes for single-channel frame buffer formats with two, four, and sixteen brightness levels, where there is a direct relationship between channel value and brightness. As the number of bits per pixel is less than eight, these rely on proper block handling for the calculation of bits per pixel and pitch. The fill order (the order in which multiple pixels are packed in a byte) is the same order as used for grayscale (2, 4, and 16 levels) images in the PNG specification, Version 1.2. This order is also the recommended and default order (FillOrder = 1) for bilevel and grayscale (16 levels) images in the TIFF 6.0 Specification, and is also used for monochrome images in the PBM file format, monochrome Linux frame buffer logos, and BDF and PSF (Linux kernel) font files. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/96561a88e53c59cac72e66642bf4c097aacefd18.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_fourcc.c | 6 ++++++ include/uapi/drm/drm_fourcc.h | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 29f4fe199c4d..05e65e9ab0c6 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -154,6 +154,12 @@ const struct drm_format_info *__drm_format_info(u32 format) { .format = DRM_FORMAT_C4, .depth = 4, .num_planes = 1, .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, + { .format = DRM_FORMAT_R1, .depth = 1, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_R2, .depth = 2, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_R4, .depth = 4, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R10, .depth = 10, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R12, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 9521057701c4..6190fe3c6cc8 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -104,6 +104,15 @@ extern "C" { #define DRM_FORMAT_C4 fourcc_code('C', '4', ' ', ' ') /* [7:0] C0:C1 4:4 two pixels/byte */ #define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ +/* 1 bpp Red (direct relationship between channel value and brightness) */ +#define DRM_FORMAT_R1 fourcc_code('R', '1', ' ', ' ') /* [7:0] R0:R1:R2:R3:R4:R5:R6:R7 1:1:1:1:1:1:1:1 eight pixels/byte */ + +/* 2 bpp Red (direct relationship between channel value and brightness) */ +#define DRM_FORMAT_R2 fourcc_code('R', '2', ' ', ' ') /* [7:0] R0:R1:R2:R3 2:2:2:2 four pixels/byte */ + +/* 4 bpp Red (direct relationship between channel value and brightness) */ +#define DRM_FORMAT_R4 fourcc_code('R', '4', ' ', ' ') /* [7:0] R0:R1 4:4 two pixels/byte */ + /* 8 bpp Red (direct relationship between channel value and brightness) */ #define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ From b92db7e4fe740daab858366faff1f992d53d3ff4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:20:55 +0200 Subject: [PATCH 021/396] drm/fourcc: Add DRM_FORMAT_D[1248] As Rn covers single-channel formats with a direct relationship between channel value and brightness, and Cn can be any colors, there are currently no fourcc codes to describe single-channel formats with an inverse relationship between channel value and brightness. Introduce fourcc codes for a single-channel frame buffer format with two, four, sixteen, or 256 brightness ("darkness") levels, where there is an inverse relationship between channel value and brightness. As the number of bits per pixel may be less than eight, some of these formats rely on proper block handling for the calculation of bits per pixel and pitch. The fill order (the order in which multiple pixels are packed in a byte) is the same order as used for grayscale (2, 4, and 16 levels) images in the PNG specification, Version 1.2. This order is also the recommended and default order (FillOrder = 1) for bilevel and grayscale (16 levels) images in the TIFF 6.0 Specification, and is also used for monochrome images in the PBM file format, monochrome Linux frame buffer logos, and BDF and PSF (Linux kernel) font files. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/6119f3abeda9baaa88652843960adc032da276b4.1657294931.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_fourcc.c | 7 +++++++ include/uapi/drm/drm_fourcc.h | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 05e65e9ab0c6..e09331bb3bc7 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -154,6 +154,13 @@ const struct drm_format_info *__drm_format_info(u32 format) { .format = DRM_FORMAT_C4, .depth = 4, .num_planes = 1, .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, + { .format = DRM_FORMAT_D1, .depth = 1, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_D2, .depth = 2, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_D4, .depth = 4, .num_planes = 1, + .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_D8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R1, .depth = 1, .num_planes = 1, .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_R2, .depth = 2, .num_planes = 1, diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 6190fe3c6cc8..80e0d432029c 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -104,6 +104,18 @@ extern "C" { #define DRM_FORMAT_C4 fourcc_code('C', '4', ' ', ' ') /* [7:0] C0:C1 4:4 two pixels/byte */ #define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ +/* 1 bpp Darkness (inverse relationship between channel value and brightness) */ +#define DRM_FORMAT_D1 fourcc_code('D', '1', ' ', ' ') /* [7:0] D0:D1:D2:D3:D4:D5:D6:D7 1:1:1:1:1:1:1:1 eight pixels/byte */ + +/* 2 bpp Darkness (inverse relationship between channel value and brightness) */ +#define DRM_FORMAT_D2 fourcc_code('D', '2', ' ', ' ') /* [7:0] D0:D1:D2:D3 2:2:2:2 four pixels/byte */ + +/* 4 bpp Darkness (inverse relationship between channel value and brightness) */ +#define DRM_FORMAT_D4 fourcc_code('D', '4', ' ', ' ') /* [7:0] D0:D1 4:4 two pixels/byte */ + +/* 8 bpp Darkness (inverse relationship between channel value and brightness) */ +#define DRM_FORMAT_D8 fourcc_code('D', '8', ' ', ' ') /* [7:0] D */ + /* 1 bpp Red (direct relationship between channel value and brightness) */ #define DRM_FORMAT_R1 fourcc_code('R', '1', ' ', ' ') /* [7:0] R0:R1:R2:R3:R4:R5:R6:R7 1:1:1:1:1:1:1:1 eight pixels/byte */ From 0c05fcd3b45d6769c496fc6e2b88d18fc78ebe11 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Wed, 6 Jul 2022 15:20:18 +0200 Subject: [PATCH 022/396] drm/mode: Improve drm_mode_fb_cmd2 documentation Fix various grammar mistakes in the kerneldoc comments documenting the drm_mode_fb_cmd2 structure: - s/is/are/, - s/8 bit/8-bit/. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Simon Ser <contact@emersion.fr> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/536de72eab09242e1faf22fa58d91c9005d6ea51.1657113597.git.geert@linux-m68k.org Link: https://patchwork.freedesktop.org/patch/msgid/20220608020614.4098292-1-bjorn.andersson@linaro.org --- include/uapi/drm/drm_mode.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 0a0d56a6158e..fa953309d9ce 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -675,11 +675,11 @@ struct drm_mode_fb_cmd { * fetch metadata about an existing frame-buffer. * * In case of planar formats, this struct allows up to 4 buffer objects with - * offsets and pitches per plane. The pitch and offset order is dictated by the - * format FourCC as defined by ``drm_fourcc.h``, e.g. NV12 is described as: + * offsets and pitches per plane. The pitch and offset order are dictated by + * the format FourCC as defined by ``drm_fourcc.h``, e.g. NV12 is described as: * - * YUV 4:2:0 image with a plane of 8 bit Y samples followed by an - * interleaved U/V plane containing 8 bit 2x2 subsampled colour difference + * YUV 4:2:0 image with a plane of 8-bit Y samples followed by an + * interleaved U/V plane containing 8-bit 2x2 subsampled colour difference * samples. * * So it would consist of a Y plane at ``offsets[0]`` and a UV plane at From 2b50aae61f94bc76dde7d4c87b610ffe45ca1b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=BCcker?= <martin.juecker@gmail.com> Date: Mon, 16 May 2022 21:37:07 +0200 Subject: [PATCH 023/396] dt-bindings: display: simple: add support for Samsung LTL101AL01 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the Samsung LTL101AL01 WXGA LCD panel to the list. Signed-off-by: Martin Jücker <martin.juecker@gmail.com> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220516193709.10037-1-martin.juecker@gmail.com --- .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index bc8e9c0c1dc3..133f2bae04b5 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -280,6 +280,8 @@ properties: - samsung,atna33xc20 # Samsung 12.2" (2560x1600 pixels) TFT LCD panel - samsung,lsn122dl01-c01 + # Samsung Electronics 10.1" WXGA (1280x800) TFT LCD panel + - samsung,ltl101al01 # Samsung Electronics 10.1" WSVGA TFT LCD panel - samsung,ltn101nt05 # Samsung Electronics 14" WXGA (1366x768) TFT LCD panel From a6aa679a70e9d8fa4ad3f519c060db9bb186e21c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=BCcker?= <martin.juecker@gmail.com> Date: Mon, 16 May 2022 21:37:08 +0200 Subject: [PATCH 024/396] drm/panel: simple: add support for the Samsung LTL101AL01 panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add timings and panel description for the Samsung LTL101AL01 panel. Signed-off-by: Martin Jücker <martin.juecker@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220516193709.10037-2-martin.juecker@gmail.com --- drivers/gpu/drm/panel/panel-simple.c | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index c1d224cb719d..edd5a0c35437 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3218,6 +3218,37 @@ static const struct panel_desc rocktech_rk101ii01d_ct = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; +static const struct display_timing samsung_ltl101al01_timing = { + .pixelclock = { 66663000, 66663000, 66663000 }, + .hactive = { 1280, 1280, 1280 }, + .hfront_porch = { 18, 18, 18 }, + .hback_porch = { 36, 36, 36 }, + .hsync_len = { 16, 16, 16 }, + .vactive = { 800, 800, 800 }, + .vfront_porch = { 4, 4, 4 }, + .vback_porch = { 16, 16, 16 }, + .vsync_len = { 3, 3, 3 }, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc samsung_ltl101al01 = { + .timings = &samsung_ltl101al01_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 217, + .height = 135, + }, + .delay = { + .prepare = 40, + .enable = 300, + .disable = 200, + .unprepare = 600, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode samsung_ltn101nt05_mode = { .clock = 54030, .hdisplay = 1024, @@ -4161,6 +4192,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "rocktech,rk101ii01d-ct", .data = &rocktech_rk101ii01d_ct, + }, { + .compatible = "samsung,ltl101al01", + .data = &samsung_ltl101al01, }, { .compatible = "samsung,ltn101nt05", .data = &samsung_ltn101nt05, From 6de745238aa30529778a26622a430dfcb171b089 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Wed, 6 Jul 2022 15:16:18 +0200 Subject: [PATCH 025/396] drm/fb: Improve drm_framebuffer.offsets documentation Fix various spelling and grammar mistakes in the kerneldoc comments documenting the offsets member in the drm_framebuffer structure: - s/laytou/layout/, - Add missing "is", - s/it/its/. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Simon Ser <contact@emersion.fr> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/33fda13b500b39645e7363806c6e458e915b581e.1657113304.git.geert@linux-m68k.org --- include/drm/drm_framebuffer.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index f67c5b7bcb68..0dcc07b68654 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -154,10 +154,10 @@ struct drm_framebuffer { * drm_mode_fb_cmd2. * * Note that this is a linear offset and does not take into account - * tiling or buffer laytou per @modifier. It meant to be used when the - * actual pixel data for this framebuffer plane starts at an offset, - * e.g. when multiple planes are allocated within the same backing - * storage buffer object. For tiled layouts this generally means it + * tiling or buffer layout per @modifier. It is meant to be used when + * the actual pixel data for this framebuffer plane starts at an offset, + * e.g. when multiple planes are allocated within the same backing + * storage buffer object. For tiled layouts this generally means its * @offsets must at least be tile-size aligned, but hardware often has * stricter requirements. * From 46f4433550084de3bb288cbb32fbdad7688de11e Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Fri, 8 Jul 2022 21:54:01 +0100 Subject: [PATCH 026/396] dt-bindings/display: ingenic: Add compatible string for the JZ4760(B) Add compatible strings for the LCD controllers found in the JZ4760 and JZ4760B SoCs from Ingenic. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Sam Ravnborg <sam@ravnborg.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org> Cc: devicetree@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20220708205406.96473-2-paul@crapouillou.net --- Documentation/devicetree/bindings/display/ingenic,lcd.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/ingenic,lcd.yaml b/Documentation/devicetree/bindings/display/ingenic,lcd.yaml index 0049010b37ca..c0bb02fb49f4 100644 --- a/Documentation/devicetree/bindings/display/ingenic,lcd.yaml +++ b/Documentation/devicetree/bindings/display/ingenic,lcd.yaml @@ -17,6 +17,8 @@ properties: enum: - ingenic,jz4740-lcd - ingenic,jz4725b-lcd + - ingenic,jz4760-lcd + - ingenic,jz4760b-lcd - ingenic,jz4770-lcd - ingenic,jz4780-lcd From 2ad5a3ac9dc6c98a045385dc8667e9499577a325 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Fri, 8 Jul 2022 21:54:02 +0100 Subject: [PATCH 027/396] drm/ingenic: Fix MODULE_LICENSE() string The previous "GPL v2" string is deprecated. For more info, see commit bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220708205406.96473-3-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index eb8208bfe5ab..e435c19d54d5 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -1616,4 +1616,4 @@ module_exit(ingenic_drm_exit); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); From d292dc324425995d7a45b07f3abf9a9919f3a1a9 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Fri, 8 Jul 2022 21:54:03 +0100 Subject: [PATCH 028/396] drm/ingenic: Add support for the JZ4760(B) Add support for the JZ4760 and JZ4760B SoCs to the ingenic-drm display driver. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220708205406.96473-4-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index e435c19d54d5..78d0b035e2d7 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -1541,6 +1541,32 @@ static const struct jz_soc_info jz4725b_soc_info = { .num_formats_f0 = ARRAY_SIZE(jz4725b_formats_f0), }; +static const struct jz_soc_info jz4760_soc_info = { + .needs_dev_clk = false, + .has_osd = true, + .map_noncoherent = false, + .max_width = 1280, + .max_height = 720, + .max_burst = JZ_LCD_CTRL_BURST_32, + .formats_f1 = jz4770_formats_f1, + .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1), + .formats_f0 = jz4770_formats_f0, + .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), +}; + +static const struct jz_soc_info jz4760b_soc_info = { + .needs_dev_clk = false, + .has_osd = true, + .map_noncoherent = false, + .max_width = 1280, + .max_height = 720, + .max_burst = JZ_LCD_CTRL_BURST_64, + .formats_f1 = jz4770_formats_f1, + .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1), + .formats_f0 = jz4770_formats_f0, + .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), +}; + static const struct jz_soc_info jz4770_soc_info = { .needs_dev_clk = false, .has_osd = true, @@ -1572,6 +1598,8 @@ static const struct jz_soc_info jz4780_soc_info = { static const struct of_device_id ingenic_drm_of_match[] = { { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info }, { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info }, + { .compatible = "ingenic,jz4760-lcd", .data = &jz4760_soc_info }, + { .compatible = "ingenic,jz4760b-lcd", .data = &jz4760b_soc_info }, { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info }, { .compatible = "ingenic,jz4780-lcd", .data = &jz4780_soc_info }, { /* sentinel */ }, From c167ee1f75ca5947bafe93ab23b007cb243e5f4a Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Fri, 8 Jul 2022 21:54:04 +0100 Subject: [PATCH 029/396] drm/ingenic: Don't request full modeset if property is not modified Avoid requesting a full modeset if the sharpness property is not modified, because then we don't actually need it. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220708205406.96473-5-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-ipu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 32a50935aa6d..d13f58ad4769 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -697,10 +697,12 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane *plane, { struct ingenic_ipu *ipu = plane_to_ingenic_ipu(plane); struct drm_crtc_state *crtc_state; + bool mode_changed; if (property != ipu->sharpness_prop) return -EINVAL; + mode_changed = val != ipu->sharpness; ipu->sharpness = val; if (state->crtc) { @@ -708,7 +710,7 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane *plane, if (WARN_ON(!crtc_state)) return -EINVAL; - crtc_state->mode_changed = true; + crtc_state->mode_changed |= mode_changed; } return 0; From 006f3b2f324cb2277bdcb89693296d9647ece251 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Fri, 8 Jul 2022 21:54:06 +0100 Subject: [PATCH 030/396] drm/ingenic: Use the new PM macros - Use DEFINE_SIMPLE_DEV_PM_OPS() instead of the SIMPLE_DEV_PM_OPS() macro. This makes it possible to remove the __maybe_unused flags on the callback functions. - Since we only have callbacks for suspend/resume, we can conditionally compile the dev_pm_ops structure for when CONFIG_PM_SLEEP is enabled; so use the pm_sleep_ptr() macro instead of pm_ptr(). Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220708205406.96473-7-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 78d0b035e2d7..4de729bbf152 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -1464,21 +1464,22 @@ static int ingenic_drm_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused ingenic_drm_suspend(struct device *dev) +static int ingenic_drm_suspend(struct device *dev) { struct ingenic_drm *priv = dev_get_drvdata(dev); return drm_mode_config_helper_suspend(&priv->drm); } -static int __maybe_unused ingenic_drm_resume(struct device *dev) +static int ingenic_drm_resume(struct device *dev) { struct ingenic_drm *priv = dev_get_drvdata(dev); return drm_mode_config_helper_resume(&priv->drm); } -static SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops, ingenic_drm_suspend, ingenic_drm_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops, + ingenic_drm_suspend, ingenic_drm_resume); static const u32 jz4740_formats[] = { DRM_FORMAT_XRGB1555, @@ -1609,7 +1610,7 @@ MODULE_DEVICE_TABLE(of, ingenic_drm_of_match); static struct platform_driver ingenic_drm_driver = { .driver = { .name = "ingenic-drm", - .pm = pm_ptr(&ingenic_drm_pm_ops), + .pm = pm_sleep_ptr(&ingenic_drm_pm_ops), .of_match_table = of_match_ptr(ingenic_drm_of_match), }, .probe = ingenic_drm_probe, From d395fb1999abb7eaa3fb5fd2107cae0f1e41e6d0 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Fri, 8 Jul 2022 02:30:45 -0700 Subject: [PATCH 031/396] Revert "drm/amdgpu: move internal vram_mgr function into the C file" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 708d19d9f362766147cab79eccae60912c6d3068. This is part of a revert of the following commits: commit 708d19d9f362 ("drm/amdgpu: move internal vram_mgr function into the C file") commit 5e3f1e7729ec ("drm/amdgpu: fix start calculation in amdgpu_vram_mgr_new") commit c9cad937c0c5 ("drm/amdgpu: add drm buddy support to amdgpu") [WHY] Few users reported garbaged graphics as soon as x starts, reverting until this can be resolved. Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708093047.492662-1-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 29 -------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 27 ++++++++++++++++++ 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 7a5e8a7b4a1b..51d9d3a4456c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -50,35 +50,6 @@ to_amdgpu_device(struct amdgpu_vram_mgr *mgr) return container_of(mgr, struct amdgpu_device, mman.vram_mgr); } -static inline struct drm_buddy_block * -amdgpu_vram_mgr_first_block(struct list_head *list) -{ - return list_first_entry_or_null(list, struct drm_buddy_block, link); -} - -static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head) -{ - struct drm_buddy_block *block; - u64 start, size; - - block = amdgpu_vram_mgr_first_block(head); - if (!block) - return false; - - while (head != block->link.next) { - start = amdgpu_vram_mgr_block_start(block); - size = amdgpu_vram_mgr_block_size(block); - - block = list_entry(block->link.next, struct drm_buddy_block, link); - if (start + size != amdgpu_vram_mgr_block_start(block)) - return false; - } - - return true; -} - - - /** * DOC: mem_info_vram_total * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h index 4b267bf1c5db..9a2db87186c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h @@ -53,6 +53,33 @@ static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block) return PAGE_SIZE << drm_buddy_block_order(block); } +static inline struct drm_buddy_block * +amdgpu_vram_mgr_first_block(struct list_head *list) +{ + return list_first_entry_or_null(list, struct drm_buddy_block, link); +} + +static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head) +{ + struct drm_buddy_block *block; + u64 start, size; + + block = amdgpu_vram_mgr_first_block(head); + if (!block) + return false; + + while (head != block->link.next) { + start = amdgpu_vram_mgr_block_start(block); + size = amdgpu_vram_mgr_block_size(block); + + block = list_entry(block->link.next, struct drm_buddy_block, link); + if (start + size != amdgpu_vram_mgr_block_start(block)) + return false; + } + + return true; +} + static inline struct amdgpu_vram_mgr_resource * to_amdgpu_vram_mgr_resource(struct ttm_resource *res) { From 20529e260ff2fb4a00b54a1e625ebebe5d1a6210 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Fri, 8 Jul 2022 02:30:46 -0700 Subject: [PATCH 032/396] Revert "drm/amdgpu: fix start calculation in amdgpu_vram_mgr_new" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 5e3f1e7729ec7a99e145e9d8ed58963d86cdfb98. This is part of a revert of the following commits: commit 708d19d9f362 ("drm/amdgpu: move internal vram_mgr function into the C file") commit 5e3f1e7729ec ("drm/amdgpu: fix start calculation in amdgpu_vram_mgr_new") commit c9cad937c0c5 ("drm/amdgpu: add drm buddy support to amdgpu") [WHY] Few users reported garbaged graphics as soon as x starts, reverting until this can be resolved. Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708093047.492662-2-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 22 +++++++------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 51d9d3a4456c..49e4092f447f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -496,23 +496,17 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, list_splice_tail(trim_list, &vres->blocks); } - vres->base.start = 0; - list_for_each_entry(block, &vres->blocks, link) { - unsigned long start; - - start = amdgpu_vram_mgr_block_start(block) + - amdgpu_vram_mgr_block_size(block); - start >>= PAGE_SHIFT; - - if (start > vres->base.num_pages) - start -= vres->base.num_pages; - else - start = 0; - vres->base.start = max(vres->base.start, start); - + list_for_each_entry(block, &vres->blocks, link) vis_usage += amdgpu_vram_mgr_vis_size(adev, block); + + block = amdgpu_vram_mgr_first_block(&vres->blocks); + if (!block) { + r = -EINVAL; + goto error_fini; } + vres->base.start = amdgpu_vram_mgr_block_start(block) >> PAGE_SHIFT; + if (amdgpu_is_vram_mgr_blocks_contiguous(&vres->blocks)) vres->base.placement |= TTM_PL_FLAG_CONTIGUOUS; From 347987a2cf0d146484d1c586951ef10028bb1674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 18 Feb 2022 14:32:53 +0100 Subject: [PATCH 033/396] drm/ttm: rename and cleanup ttm_bo_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename ttm_bo_init to ttm_bo_init_validate since that better matches what the function is actually doing. Remove the unused size parameter, move the function's kerneldoc to the implementation and cleanup the whole error handling. Signed-off-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220707102453.3633-2-christian.koenig@amd.com Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- drivers/gpu/drm/drm_gem_vram_helper.c | 6 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 5 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 +- drivers/gpu/drm/qxl/qxl_object.c | 2 +- drivers/gpu/drm/radeon/radeon_object.c | 6 +- drivers/gpu/drm/ttm/ttm_bo.c | 147 +++++++++++++++------ drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 12 +- include/drm/ttm/ttm_bo_api.h | 93 ++----------- 9 files changed, 129 insertions(+), 150 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 2c82b1d5a0d7..d9cfe259f2a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -591,7 +591,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, if (!bp->destroy) bp->destroy = &amdgpu_bo_destroy; - r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, bp->type, + r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, bp->type, &bo->placement, page_align, &ctx, NULL, bp->resv, bp->destroy); if (unlikely(r != 0)) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index d607043716d3..125160b534be 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -226,9 +226,9 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, * A failing ttm_bo_init will call ttm_buffer_object_destroy * to release gbo->bo.base and kfree gbo. */ - ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device, - &gbo->placement, pg_align, false, NULL, NULL, - ttm_buffer_object_destroy); + ret = ttm_bo_init_validate(bdev, &gbo->bo, ttm_bo_type_device, + &gbo->placement, pg_align, false, NULL, NULL, + ttm_buffer_object_destroy); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 4c25d9b2f138..70e2ed4e99df 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -1229,9 +1229,8 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem, * Similarly, in delayed_destroy, we can't call ttm_bo_put() * until successful initialization. */ - ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), size, - bo_type, &i915_sys_placement, - page_size >> PAGE_SHIFT, + ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), bo_type, + &i915_sys_placement, page_size >> PAGE_SHIFT, &ctx, NULL, NULL, i915_ttm_bo_destroy); if (ret) return i915_ttm_err_to_gem(ret); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index d0887438b07e..994879d9db74 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -309,9 +309,9 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 domain, nouveau_bo_placement_set(nvbo, domain, 0); INIT_LIST_HEAD(&nvbo->io_reserve_lru); - ret = ttm_bo_init(nvbo->bo.bdev, &nvbo->bo, size, type, - &nvbo->placement, align >> PAGE_SHIFT, false, sg, - robj, nouveau_bo_del_ttm); + ret = ttm_bo_init_validate(nvbo->bo.bdev, &nvbo->bo, type, + &nvbo->placement, align >> PAGE_SHIFT, false, + sg, robj, nouveau_bo_del_ttm); if (ret) { /* ttm will call nouveau_bo_del_ttm if it fails.. */ return ret; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index b42a657e4c2f..695d9308d1f0 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -141,7 +141,7 @@ int qxl_bo_create(struct qxl_device *qdev, unsigned long size, qxl_ttm_placement_from_domain(bo, domain); bo->tbo.priority = priority; - r = ttm_bo_init_reserved(&qdev->mman.bdev, &bo->tbo, size, type, + r = ttm_bo_init_reserved(&qdev->mman.bdev, &bo->tbo, type, &bo->placement, 0, &ctx, NULL, NULL, &qxl_ttm_bo_destroy); if (unlikely(r != 0)) { diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 6c4a6802ca96..00c33b24d5d3 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -202,9 +202,9 @@ int radeon_bo_create(struct radeon_device *rdev, radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ down_read(&rdev->pm.mclk_lock); - r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, - &bo->placement, page_align, !kernel, sg, resv, - &radeon_ttm_bo_destroy); + r = ttm_bo_init_validate(&rdev->mman.bdev, &bo->tbo, type, + &bo->placement, page_align, !kernel, sg, resv, + &radeon_ttm_bo_destroy); up_read(&rdev->pm.mclk_lock); if (unlikely(r != 0)) { return r; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 296af2b89951..dbd331939e6d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -915,36 +915,61 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_validate); -int ttm_bo_init_reserved(struct ttm_device *bdev, - struct ttm_buffer_object *bo, - size_t size, - enum ttm_bo_type type, - struct ttm_placement *placement, - uint32_t page_alignment, - struct ttm_operation_ctx *ctx, - struct sg_table *sg, - struct dma_resv *resv, +/** + * ttm_bo_init_reserved + * + * @bdev: Pointer to a ttm_device struct. + * @bo: Pointer to a ttm_buffer_object to be initialized. + * @type: Requested type of buffer object. + * @placement: Initial placement for buffer object. + * @alignment: Data alignment in pages. + * @ctx: TTM operation context for memory allocation. + * @sg: Scatter-gather table. + * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. + * @destroy: Destroy function. Use NULL for kfree(). + * + * This function initializes a pre-allocated struct ttm_buffer_object. + * As this object may be part of a larger structure, this function, + * together with the @destroy function, enables driver-specific objects + * derived from a ttm_buffer_object. + * + * On successful return, the caller owns an object kref to @bo. The kref and + * list_kref are usually set to 1, but note that in some situations, other + * tasks may already be holding references to @bo as well. + * Furthermore, if resv == NULL, the buffer's reservation lock will be held, + * and it is the caller's responsibility to call ttm_bo_unreserve. + * + * If a failure occurs, the function will call the @destroy function. Thus, + * after a failure, dereferencing @bo is illegal and will likely cause memory + * corruption. + * + * Returns + * -ENOMEM: Out of memory. + * -EINVAL: Invalid placement flags. + * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. + */ +int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, + enum ttm_bo_type type, struct ttm_placement *placement, + uint32_t alignment, struct ttm_operation_ctx *ctx, + struct sg_table *sg, struct dma_resv *resv, void (*destroy) (struct ttm_buffer_object *)) { static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM }; - bool locked; int ret; - bo->destroy = destroy; kref_init(&bo->kref); INIT_LIST_HEAD(&bo->ddestroy); bo->bdev = bdev; bo->type = type; - bo->page_alignment = page_alignment; + bo->page_alignment = alignment; + bo->destroy = destroy; bo->pin_count = 0; bo->sg = sg; bo->bulk_move = NULL; - if (resv) { + if (resv) bo->base.resv = resv; - dma_resv_assert_held(bo->base.resv); - } else { + else bo->base.resv = &bo->base._resv; - } atomic_inc(&ttm_glob.bo_count); ret = ttm_resource_alloc(bo, &sys_mem, &bo->resource); @@ -957,50 +982,84 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, * For ttm_bo_type_device buffers, allocate * address space from the device. */ - if (bo->type == ttm_bo_type_device || - bo->type == ttm_bo_type_sg) + if (bo->type == ttm_bo_type_device || bo->type == ttm_bo_type_sg) { ret = drm_vma_offset_add(bdev->vma_manager, &bo->base.vma_node, - bo->resource->num_pages); + PFN_UP(bo->base.size)); + if (ret) + goto err_put; + } /* passed reservation objects should already be locked, * since otherwise lockdep will be angered in radeon. */ - if (!resv) { - locked = dma_resv_trylock(bo->base.resv); - WARN_ON(!locked); - } + if (!resv) + WARN_ON(!dma_resv_trylock(bo->base.resv)); + else + dma_resv_assert_held(resv); - if (likely(!ret)) - ret = ttm_bo_validate(bo, placement, ctx); + ret = ttm_bo_validate(bo, placement, ctx); + if (unlikely(ret)) + goto err_unlock; - if (unlikely(ret)) { - if (!resv) - ttm_bo_unreserve(bo); + return 0; - ttm_bo_put(bo); - return ret; - } +err_unlock: + if (!resv) + dma_resv_unlock(bo->base.resv); +err_put: + ttm_bo_put(bo); return ret; } EXPORT_SYMBOL(ttm_bo_init_reserved); -int ttm_bo_init(struct ttm_device *bdev, - struct ttm_buffer_object *bo, - size_t size, - enum ttm_bo_type type, - struct ttm_placement *placement, - uint32_t page_alignment, - bool interruptible, - struct sg_table *sg, - struct dma_resv *resv, - void (*destroy) (struct ttm_buffer_object *)) +/** + * ttm_bo_init_validate + * + * @bdev: Pointer to a ttm_device struct. + * @bo: Pointer to a ttm_buffer_object to be initialized. + * @type: Requested type of buffer object. + * @placement: Initial placement for buffer object. + * @alignment: Data alignment in pages. + * @interruptible: If needing to sleep to wait for GPU resources, + * sleep interruptible. + * pinned in physical memory. If this behaviour is not desired, this member + * holds a pointer to a persistent shmem object. Typically, this would + * point to the shmem object backing a GEM object if TTM is used to back a + * GEM user interface. + * @sg: Scatter-gather table. + * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. + * @destroy: Destroy function. Use NULL for kfree(). + * + * This function initializes a pre-allocated struct ttm_buffer_object. + * As this object may be part of a larger structure, this function, + * together with the @destroy function, + * enables driver-specific objects derived from a ttm_buffer_object. + * + * On successful return, the caller owns an object kref to @bo. The kref and + * list_kref are usually set to 1, but note that in some situations, other + * tasks may already be holding references to @bo as well. + * + * If a failure occurs, the function will call the @destroy function, Thus, + * after a failure, dereferencing @bo is illegal and will likely cause memory + * corruption. + * + * Returns + * -ENOMEM: Out of memory. + * -EINVAL: Invalid placement flags. + * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. + */ +int ttm_bo_init_validate(struct ttm_device *bdev, struct ttm_buffer_object *bo, + enum ttm_bo_type type, struct ttm_placement *placement, + uint32_t alignment, bool interruptible, + struct sg_table *sg, struct dma_resv *resv, + void (*destroy) (struct ttm_buffer_object *)) { struct ttm_operation_ctx ctx = { interruptible, false }; int ret; - ret = ttm_bo_init_reserved(bdev, bo, size, type, placement, - page_alignment, &ctx, sg, resv, destroy); + ret = ttm_bo_init_reserved(bdev, bo, type, placement, alignment, &ctx, + sg, resv, destroy); if (ret) return ret; @@ -1009,7 +1068,7 @@ int ttm_bo_init(struct ttm_device *bdev, return 0; } -EXPORT_SYMBOL(ttm_bo_init); +EXPORT_SYMBOL(ttm_bo_init_validate); /* * buffer object vm functions. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 85a66014c2b6..eb2fd7694cd1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -429,9 +429,9 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, drm_gem_private_object_init(vdev, &bo->base, size); - ret = ttm_bo_init_reserved(&dev_priv->bdev, bo, size, - ttm_bo_type_kernel, placement, 0, - &ctx, NULL, NULL, vmw_bo_default_destroy); + ret = ttm_bo_init_reserved(&dev_priv->bdev, bo, ttm_bo_type_kernel, + placement, 0, &ctx, NULL, NULL, + vmw_bo_default_destroy); if (unlikely(ret)) goto error_free; @@ -512,10 +512,8 @@ int vmw_bo_init(struct vmw_private *dev_priv, size = ALIGN(size, PAGE_SIZE); drm_gem_private_object_init(vdev, &vmw_bo->base.base, size); - ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, size, - ttm_bo_type_device, - placement, - 0, &ctx, NULL, NULL, bo_free); + ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device, + placement, 0, &ctx, NULL, NULL, bo_free); if (unlikely(ret)) { return ret; } diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 2d524f8b0802..44a538ee5e2a 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -317,93 +317,16 @@ void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched); bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place); -/** - * ttm_bo_init_reserved - * - * @bdev: Pointer to a ttm_device struct. - * @bo: Pointer to a ttm_buffer_object to be initialized. - * @size: Requested size of buffer object. - * @type: Requested type of buffer object. - * @placement: Initial placement for buffer object. - * @page_alignment: Data alignment in pages. - * @ctx: TTM operation context for memory allocation. - * @sg: Scatter-gather table. - * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. - * @destroy: Destroy function. Use NULL for kfree(). - * - * This function initializes a pre-allocated struct ttm_buffer_object. - * As this object may be part of a larger structure, this function, - * together with the @destroy function, - * enables driver-specific objects derived from a ttm_buffer_object. - * - * On successful return, the caller owns an object kref to @bo. The kref and - * list_kref are usually set to 1, but note that in some situations, other - * tasks may already be holding references to @bo as well. - * Furthermore, if resv == NULL, the buffer's reservation lock will be held, - * and it is the caller's responsibility to call ttm_bo_unreserve. - * - * If a failure occurs, the function will call the @destroy function, or - * kfree() if @destroy is NULL. Thus, after a failure, dereferencing @bo is - * illegal and will likely cause memory corruption. - * - * Returns - * -ENOMEM: Out of memory. - * -EINVAL: Invalid placement flags. - * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. - */ - -int ttm_bo_init_reserved(struct ttm_device *bdev, - struct ttm_buffer_object *bo, - size_t size, enum ttm_bo_type type, - struct ttm_placement *placement, - uint32_t page_alignment, - struct ttm_operation_ctx *ctx, +int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, + enum ttm_bo_type type, struct ttm_placement *placement, + uint32_t alignment, struct ttm_operation_ctx *ctx, + struct sg_table *sg, struct dma_resv *resv, + void (*destroy) (struct ttm_buffer_object *)); +int ttm_bo_init_validate(struct ttm_device *bdev, struct ttm_buffer_object *bo, + enum ttm_bo_type type, struct ttm_placement *placement, + uint32_t alignment, bool interruptible, struct sg_table *sg, struct dma_resv *resv, void (*destroy) (struct ttm_buffer_object *)); - -/** - * ttm_bo_init - * - * @bdev: Pointer to a ttm_device struct. - * @bo: Pointer to a ttm_buffer_object to be initialized. - * @size: Requested size of buffer object. - * @type: Requested type of buffer object. - * @placement: Initial placement for buffer object. - * @page_alignment: Data alignment in pages. - * @interruptible: If needing to sleep to wait for GPU resources, - * sleep interruptible. - * pinned in physical memory. If this behaviour is not desired, this member - * holds a pointer to a persistent shmem object. Typically, this would - * point to the shmem object backing a GEM object if TTM is used to back a - * GEM user interface. - * @sg: Scatter-gather table. - * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. - * @destroy: Destroy function. Use NULL for kfree(). - * - * This function initializes a pre-allocated struct ttm_buffer_object. - * As this object may be part of a larger structure, this function, - * together with the @destroy function, - * enables driver-specific objects derived from a ttm_buffer_object. - * - * On successful return, the caller owns an object kref to @bo. The kref and - * list_kref are usually set to 1, but note that in some situations, other - * tasks may already be holding references to @bo as well. - * - * If a failure occurs, the function will call the @destroy function, or - * kfree() if @destroy is NULL. Thus, after a failure, dereferencing @bo is - * illegal and will likely cause memory corruption. - * - * Returns - * -ENOMEM: Out of memory. - * -EINVAL: Invalid placement flags. - * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. - */ -int ttm_bo_init(struct ttm_device *bdev, struct ttm_buffer_object *bo, - size_t size, enum ttm_bo_type type, - struct ttm_placement *placement, - uint32_t page_alignment, bool interrubtible, - struct sg_table *sg, struct dma_resv *resv, - void (*destroy) (struct ttm_buffer_object *)); /** * ttm_kmap_obj_virtual From 63af82cf5e36b6ba3f3ebcdd1edd9f91934bfa59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 17 Dec 2021 16:13:09 +0100 Subject: [PATCH 034/396] drm/amdgpu: audit bo->resource usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we can at least move and release BOs without backing store. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220707102453.3633-3-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index d9cfe259f2a9..677d1dfab37f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1305,7 +1305,7 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) if (bo->base.resv == &bo->base._resv) amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo); - if (bo->resource->mem_type != TTM_PL_VRAM || + if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM || !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) || adev->in_suspend || adev->shutdown) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index be6f76a30ac6..3bddf266e8b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -471,7 +471,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, adev = amdgpu_ttm_adev(bo->bdev); - if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { + if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && + bo->ttm == NULL)) { ttm_bo_move_null(bo, new_mem); goto out; } From 64e257f187a5c76ec5766f50204462c0c483e418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 17 Dec 2021 16:30:16 +0100 Subject: [PATCH 035/396] drm/nouveau: audit bo->resource usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we can at least move and release BOs without backing store. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220707102453.3633-4-christian.koenig@amd.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 994879d9db74..35bb0bb3fe61 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1008,7 +1008,8 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, } /* Fake bo copy. */ - if (old_reg->mem_type == TTM_PL_SYSTEM && !bo->ttm) { + if (!old_reg || (old_reg->mem_type == TTM_PL_SYSTEM && + !bo->ttm)) { ttm_bo_move_null(bo, new_reg); goto out; } From 4d8f68548e982e2c9b9ca3b47aea49c47da93a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 17 Feb 2022 10:43:16 +0100 Subject: [PATCH 036/396] drm/ttm: audit bo->resource usage v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow BOs to exist without backing store. v2: handle ttm_bo_move_memcpy as well. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220707102453.3633-5-christian.koenig@amd.com --- drivers/gpu/drm/ttm/ttm_bo.c | 16 ++++++++-------- drivers/gpu/drm/ttm/ttm_bo_util.c | 7 +++++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index dbd331939e6d..698918a15721 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -117,12 +117,13 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, struct ttm_place *hop) { - struct ttm_resource_manager *old_man, *new_man; struct ttm_device *bdev = bo->bdev; + bool old_use_tt, new_use_tt; int ret; - old_man = ttm_manager_type(bdev, bo->resource->mem_type); - new_man = ttm_manager_type(bdev, mem->mem_type); + old_use_tt = bo->resource && + ttm_manager_type(bdev, bo->resource->mem_type)->use_tt; + new_use_tt = ttm_manager_type(bdev, mem->mem_type)->use_tt; ttm_bo_unmap_virtual(bo); @@ -130,11 +131,11 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, * Create and bind a ttm if required. */ - if (new_man->use_tt) { + if (new_use_tt) { /* Zero init the new TTM structure if the old location should * have used one as well. */ - ret = ttm_tt_create(bo, old_man->use_tt); + ret = ttm_tt_create(bo, old_use_tt); if (ret) goto out_err; @@ -160,8 +161,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, return 0; out_err: - new_man = ttm_manager_type(bdev, bo->resource->mem_type); - if (!new_man->use_tt) + if (!old_use_tt) ttm_bo_tt_destroy(bo); return ret; @@ -898,7 +898,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, /* * Check whether we need to move buffer. */ - if (!ttm_resource_compat(bo->resource, placement)) { + if (!bo->resource || !ttm_resource_compat(bo->resource, placement)) { ret = ttm_bo_move_buffer(bo, placement, ctx); if (ret) return ret; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 1cbfb00c1d65..1530982338e9 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -137,8 +137,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, ttm_manager_type(bo->bdev, dst_mem->mem_type); struct ttm_tt *ttm = bo->ttm; struct ttm_resource *src_mem = bo->resource; - struct ttm_resource_manager *src_man = - ttm_manager_type(bdev, src_mem->mem_type); + struct ttm_resource_manager *src_man; union { struct ttm_kmap_iter_tt tt; struct ttm_kmap_iter_linear_io io; @@ -147,6 +146,10 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, bool clear; int ret = 0; + if (!src_mem) + return 0; + + src_man = ttm_manager_type(bdev, src_mem->mem_type); if (ttm && ((ttm->page_flags & TTM_TT_FLAG_SWAPPED) || dst_man->use_tt)) { ret = ttm_tt_populate(bdev, ttm, ctx); From ba8f16cd081902350e2d2a00afcc6b77b1815d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:44 -0300 Subject: [PATCH 037/396] drm: selftest: convert drm_damage_helper selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM damage helper selftest to the KUnit API. Co-developed-by: Arthur Grillo <arthur.grillo@usp.br> Signed-off-by: Arthur Grillo <arthur.grillo@usp.br> Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-2-maira.canal@usp.br --- drivers/gpu/drm/Kconfig | 8 +- drivers/gpu/drm/selftests/Makefile | 3 +- .../gpu/drm/selftests/drm_modeset_selftests.h | 21 - .../drm/selftests/test-drm_damage_helper.c | 668 ------------------ .../drm/selftests/test-drm_modeset_common.h | 21 - drivers/gpu/drm/tests/Makefile | 2 +- .../gpu/drm/tests/drm_damage_helper_test.c | 634 +++++++++++++++++ 7 files changed, 643 insertions(+), 714 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/test-drm_damage_helper.c create mode 100644 drivers/gpu/drm/tests/drm_damage_helper_test.c diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 6c2256e8474b..06822ecf51c6 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -72,8 +72,14 @@ config DRM_DEBUG_SELFTEST config DRM_KUNIT_TEST tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS - depends on DRM && KUNIT=y + depends on DRM && KUNIT + select PRIME_NUMBERS + select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HELPER + select DRM_LIB_RANDOM select DRM_KMS_HELPER + select DRM_BUDDY + select DRM_EXPORT_FOR_TESTS if m default KUNIT_ALL_TESTS help This builds unit tests for DRM. This option is not useful for diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 5ba5f9138c95..7a1a732e0a1b 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1,8 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \ test-drm_format.o test-drm_framebuffer.o \ - test-drm_damage_helper.o test-drm_dp_mst_helper.o \ - test-drm_rect.o + test-drm_dp_mst_helper.o test-drm_rect.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \ test-drm_buddy.o diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h index 782e285ca383..4787b3b70709 100644 --- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h +++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h @@ -15,26 +15,5 @@ selftest(check_drm_format_block_width, igt_check_drm_format_block_width) selftest(check_drm_format_block_height, igt_check_drm_format_block_height) selftest(check_drm_format_min_pitch, igt_check_drm_format_min_pitch) selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create) -selftest(damage_iter_no_damage, igt_damage_iter_no_damage) -selftest(damage_iter_no_damage_fractional_src, igt_damage_iter_no_damage_fractional_src) -selftest(damage_iter_no_damage_src_moved, igt_damage_iter_no_damage_src_moved) -selftest(damage_iter_no_damage_fractional_src_moved, igt_damage_iter_no_damage_fractional_src_moved) -selftest(damage_iter_no_damage_not_visible, igt_damage_iter_no_damage_not_visible) -selftest(damage_iter_no_damage_no_crtc, igt_damage_iter_no_damage_no_crtc) -selftest(damage_iter_no_damage_no_fb, igt_damage_iter_no_damage_no_fb) -selftest(damage_iter_simple_damage, igt_damage_iter_simple_damage) -selftest(damage_iter_single_damage, igt_damage_iter_single_damage) -selftest(damage_iter_single_damage_intersect_src, igt_damage_iter_single_damage_intersect_src) -selftest(damage_iter_single_damage_outside_src, igt_damage_iter_single_damage_outside_src) -selftest(damage_iter_single_damage_fractional_src, igt_damage_iter_single_damage_fractional_src) -selftest(damage_iter_single_damage_intersect_fractional_src, igt_damage_iter_single_damage_intersect_fractional_src) -selftest(damage_iter_single_damage_outside_fractional_src, igt_damage_iter_single_damage_outside_fractional_src) -selftest(damage_iter_single_damage_src_moved, igt_damage_iter_single_damage_src_moved) -selftest(damage_iter_single_damage_fractional_src_moved, igt_damage_iter_single_damage_fractional_src_moved) -selftest(damage_iter_damage, igt_damage_iter_damage) -selftest(damage_iter_damage_one_intersect, igt_damage_iter_damage_one_intersect) -selftest(damage_iter_damage_one_outside, igt_damage_iter_damage_one_outside) -selftest(damage_iter_damage_src_moved, igt_damage_iter_damage_src_moved) -selftest(damage_iter_damage_not_visible, igt_damage_iter_damage_not_visible) selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode) selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode) diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c b/drivers/gpu/drm/selftests/test-drm_damage_helper.c deleted file mode 100644 index 816e1464a98f..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_damage_helper.c +++ /dev/null @@ -1,668 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Test case for drm_damage_helper functions - */ - -#define pr_fmt(fmt) "drm_damage_helper: " fmt - -#include <drm/drm_damage_helper.h> -#include <drm/drm_framebuffer.h> -#include <drm/drm_plane.h> -#include <drm/drm_drv.h> - -#include "test-drm_modeset_common.h" - -struct drm_driver mock_driver; -static struct drm_device mock_device; -static struct drm_object_properties mock_obj_props; -static struct drm_plane mock_plane; -static struct drm_property mock_prop; - -static void mock_setup(struct drm_plane_state *state) -{ - static bool setup_done = false; - - state->plane = &mock_plane; - - if (setup_done) - return; - - /* just enough so that drm_plane_enable_fb_damage_clips() works */ - mock_device.driver = &mock_driver; - mock_device.mode_config.prop_fb_damage_clips = &mock_prop; - mock_plane.dev = &mock_device; - mock_obj_props.count = 0; - mock_plane.base.properties = &mock_obj_props; - mock_prop.base.id = 1; /* 0 is an invalid id */ - mock_prop.dev = &mock_device; - - drm_plane_enable_fb_damage_clips(&mock_plane); -} - -static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2, - int y2) -{ - state->src.x1 = x1; - state->src.y1 = y1; - state->src.x2 = x2; - state->src.y2 = y2; -} - -static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int x2, - int y2) -{ - r->x1 = x1; - r->y1 = y1; - r->x2 = x2; - r->y2 = y2; -} - -static void set_damage_blob(struct drm_property_blob *damage_blob, - struct drm_mode_rect *r, uint32_t size) -{ - damage_blob->length = size; - damage_blob->data = r; -} - -static void set_plane_damage(struct drm_plane_state *state, - struct drm_property_blob *damage_blob) -{ - state->fb_damage_clips = damage_blob; -} - -static bool check_damage_clip(struct drm_plane_state *state, struct drm_rect *r, - int x1, int y1, int x2, int y2) -{ - /* - * Round down x1/y1 and round up x2/y2. This is because damage is not in - * 16.16 fixed point so to catch all pixels. - */ - int src_x1 = state->src.x1 >> 16; - int src_y1 = state->src.y1 >> 16; - int src_x2 = (state->src.x2 >> 16) + !!(state->src.x2 & 0xFFFF); - int src_y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF); - - if (x1 >= x2 || y1 >= y2) { - pr_err("Cannot have damage clip with no dimension.\n"); - return false; - } - - if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2) { - pr_err("Damage cannot be outside rounded plane src.\n"); - return false; - } - - if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2) { - pr_err("Damage = %d %d %d %d\n", r->x1, r->y1, r->x2, r->y2); - return false; - } - - return true; -} - -const struct drm_framebuffer fb = { - .width = 2048, - .height = 2048 -}; - -/* common mocked structs many tests need */ -#define MOCK_VARIABLES() \ - struct drm_plane_state old_state; \ - struct drm_plane_state state = { \ - .crtc = ZERO_SIZE_PTR, \ - .fb = (struct drm_framebuffer *) &fb, \ - .visible = true, \ - }; \ - mock_setup(&old_state); \ - mock_setup(&state); - -int igt_damage_iter_no_damage(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src same as fb size. */ - set_plane_src(&old_state, 0, 0, fb.width << 16, fb.height << 16); - set_plane_src(&state, 0, 0, fb.width << 16, fb.height << 16); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return plane src as damage."); - FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 2048, 2048)); - - return 0; -} - -int igt_damage_iter_no_damage_fractional_src(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src has fractional part. */ - set_plane_src(&old_state, 0x3fffe, 0x3fffe, - 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); - set_plane_src(&state, 0x3fffe, 0x3fffe, - 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return rounded off plane src as damage."); - FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772)); - - return 0; -} - -int igt_damage_iter_no_damage_src_moved(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src moved since old plane state. */ - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 10 << 16, 10 << 16, - (10 + 1024) << 16, (10 + 768) << 16); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return plane src as damage."); - FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778)); - - return 0; -} - -int igt_damage_iter_no_damage_fractional_src_moved(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src has fractional part and it moved since old plane state. */ - set_plane_src(&old_state, 0x3fffe, 0x3fffe, - 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); - set_plane_src(&state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return plane src as damage."); - FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773)); - - return 0; -} - -int igt_damage_iter_no_damage_not_visible(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - state.visible = false; - - mock_setup(&old_state); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 0, "Should have no damage."); - - return 0; -} - -int igt_damage_iter_no_damage_no_crtc(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - state.crtc = NULL; - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 0, "Should have no damage."); - - return 0; -} - -int igt_damage_iter_no_damage_no_fb(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_plane_state old_state; - struct drm_rect clip; - uint32_t num_hits = 0; - - struct drm_plane_state state = { - .crtc = ZERO_SIZE_PTR, - .fb = 0, - }; - - mock_setup(&old_state); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 0, "Should have no damage."); - - return 0; -} - -int igt_damage_iter_simple_damage(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - /* Damage set to plane src */ - set_damage_clip(&damage, 0, 0, 1024, 768); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return damage when set."); - FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 1024, 768)); - - return 0; -} - -int igt_damage_iter_single_damage(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - set_damage_clip(&damage, 256, 192, 768, 576); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return damage when set."); - FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 768, 576)); - - return 0; -} - -int igt_damage_iter_single_damage_intersect_src(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - /* Damage intersect with plane src. */ - set_damage_clip(&damage, 256, 192, 1360, 768); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return damage clipped to src."); - FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 1024, 768)); - - return 0; -} - -int igt_damage_iter_single_damage_outside_src(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - /* Damage clip outside plane src */ - set_damage_clip(&damage, 1360, 1360, 1380, 1380); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 0, "Should have no damage."); - - return 0; -} - -int igt_damage_iter_single_damage_fractional_src(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src has fractional part. */ - set_plane_src(&old_state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - set_plane_src(&state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - set_damage_clip(&damage, 10, 10, 256, 330); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return damage when set."); - FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 256, 330)); - - return 0; -} - -int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src has fractional part. */ - set_plane_src(&old_state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - set_plane_src(&state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - /* Damage intersect with plane src. */ - set_damage_clip(&damage, 10, 1, 1360, 330); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return damage clipped to rounded off src."); - FAIL_ON(!check_damage_clip(&state, &clip, 10, 4, 1029, 330)); - - return 0; -} - -int igt_damage_iter_single_damage_outside_fractional_src(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src has fractional part. */ - set_plane_src(&old_state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - set_plane_src(&state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - /* Damage clip outside plane src */ - set_damage_clip(&damage, 1360, 1360, 1380, 1380); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 0, "Should have no damage."); - - return 0; -} - -int igt_damage_iter_single_damage_src_moved(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src moved since old plane state. */ - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 10 << 16, 10 << 16, - (10 + 1024) << 16, (10 + 768) << 16); - set_damage_clip(&damage, 20, 30, 256, 256); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return plane src as damage."); - FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778)); - - return 0; -} - -int igt_damage_iter_single_damage_fractional_src_moved(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - /* Plane src with fractional part moved since old plane state. */ - set_plane_src(&old_state, 0x3fffe, 0x3fffe, - 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); - set_plane_src(&state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - /* Damage intersect with plane src. */ - set_damage_clip(&damage, 20, 30, 1360, 256); - set_damage_blob(&damage_blob, &damage, sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return rounded off plane src as damage."); - FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773)); - - return 0; -} - -int igt_damage_iter_damage(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage[2]; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - /* 2 damage clips. */ - set_damage_clip(&damage[0], 20, 30, 200, 180); - set_damage_clip(&damage[1], 240, 200, 280, 250); - set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) { - if (num_hits == 0) - FAIL_ON(!check_damage_clip(&state, &clip, 20, 30, 200, 180)); - if (num_hits == 1) - FAIL_ON(!check_damage_clip(&state, &clip, 240, 200, 280, 250)); - num_hits++; - } - - FAIL(num_hits != 2, "Should return damage when set."); - - return 0; -} - -int igt_damage_iter_damage_one_intersect(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage[2]; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - set_plane_src(&state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - /* 2 damage clips, one intersect plane src. */ - set_damage_clip(&damage[0], 20, 30, 200, 180); - set_damage_clip(&damage[1], 2, 2, 1360, 1360); - set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) { - if (num_hits == 0) - FAIL_ON(!check_damage_clip(&state, &clip, 20, 30, 200, 180)); - if (num_hits == 1) - FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773)); - num_hits++; - } - - FAIL(num_hits != 2, "Should return damage when set."); - - return 0; -} - -int igt_damage_iter_damage_one_outside(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage[2]; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16); - set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16); - /* 2 damage clips, one outside plane src. */ - set_damage_clip(&damage[0], 1360, 1360, 1380, 1380); - set_damage_clip(&damage[1], 240, 200, 280, 250); - set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return damage when set."); - FAIL_ON(!check_damage_clip(&state, &clip, 240, 200, 280, 250)); - - return 0; -} - -int igt_damage_iter_damage_src_moved(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage[2]; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - set_plane_src(&old_state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - set_plane_src(&state, 0x3fffe, 0x3fffe, - 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); - /* 2 damage clips, one outside plane src. */ - set_damage_clip(&damage[0], 1360, 1360, 1380, 1380); - set_damage_clip(&damage[1], 240, 200, 280, 250); - set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 1, "Should return round off plane src as damage."); - FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772)); - - return 0; -} - -int igt_damage_iter_damage_not_visible(void *ignored) -{ - struct drm_atomic_helper_damage_iter iter; - struct drm_property_blob damage_blob; - struct drm_mode_rect damage[2]; - struct drm_rect clip; - uint32_t num_hits = 0; - - MOCK_VARIABLES(); - - state.visible = false; - - set_plane_src(&old_state, 0x40002, 0x40002, - 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); - set_plane_src(&state, 0x3fffe, 0x3fffe, - 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); - /* 2 damage clips, one outside plane src. */ - set_damage_clip(&damage[0], 1360, 1360, 1380, 1380); - set_damage_clip(&damage[1], 240, 200, 280, 250); - set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); - set_plane_damage(&state, &damage_blob); - drm_atomic_helper_damage_iter_init(&iter, &old_state, &state); - drm_atomic_for_each_plane_damage(&iter, &clip) - num_hits++; - - FAIL(num_hits != 0, "Should not return any damage."); - - return 0; -} diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h index cfb51d8da2bc..c29354e59cec 100644 --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h +++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h @@ -25,27 +25,6 @@ int igt_check_drm_format_block_width(void *ignored); int igt_check_drm_format_block_height(void *ignored); int igt_check_drm_format_min_pitch(void *ignored); int igt_check_drm_framebuffer_create(void *ignored); -int igt_damage_iter_no_damage(void *ignored); -int igt_damage_iter_no_damage_fractional_src(void *ignored); -int igt_damage_iter_no_damage_src_moved(void *ignored); -int igt_damage_iter_no_damage_fractional_src_moved(void *ignored); -int igt_damage_iter_no_damage_not_visible(void *ignored); -int igt_damage_iter_no_damage_no_crtc(void *ignored); -int igt_damage_iter_no_damage_no_fb(void *ignored); -int igt_damage_iter_simple_damage(void *ignored); -int igt_damage_iter_single_damage(void *ignored); -int igt_damage_iter_single_damage_intersect_src(void *ignored); -int igt_damage_iter_single_damage_outside_src(void *ignored); -int igt_damage_iter_single_damage_fractional_src(void *ignored); -int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored); -int igt_damage_iter_single_damage_outside_fractional_src(void *ignored); -int igt_damage_iter_single_damage_src_moved(void *ignored); -int igt_damage_iter_single_damage_fractional_src_moved(void *ignored); -int igt_damage_iter_damage(void *ignored); -int igt_damage_iter_damage_one_intersect(void *ignored); -int igt_damage_iter_damage_one_outside(void *ignored); -int igt_damage_iter_damage_src_moved(void *ignored); -int igt_damage_iter_damage_not_visible(void *ignored); int igt_dp_mst_calc_pbn_mode(void *ignored); int igt_dp_mst_sideband_msg_req_decode(void *ignored); diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 2c8273796d9d..2f399e03d50c 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o +obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c new file mode 100644 index 000000000000..bf250bd08d7e --- /dev/null +++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c @@ -0,0 +1,634 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test case for drm_damage_helper functions + * + * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> + */ + +#include <kunit/test.h> + +#include <drm/drm_damage_helper.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_plane.h> +#include <drm/drm_drv.h> + +struct drm_damage_mock { + struct drm_driver driver; + struct drm_device device; + struct drm_object_properties obj_props; + struct drm_plane plane; + struct drm_property prop; + struct drm_framebuffer fb; + struct drm_plane_state state; + struct drm_plane_state old_state; +}; + +static int drm_damage_helper_init(struct kunit *test) +{ + struct drm_damage_mock *mock; + + mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mock); + + mock->fb.width = 2048; + mock->fb.height = 2048; + + mock->state.crtc = ZERO_SIZE_PTR; + mock->state.fb = &mock->fb; + mock->state.visible = true; + + mock->old_state.plane = &mock->plane; + mock->state.plane = &mock->plane; + + /* just enough so that drm_plane_enable_fb_damage_clips() works */ + mock->device.driver = &mock->driver; + mock->device.mode_config.prop_fb_damage_clips = &mock->prop; + mock->plane.dev = &mock->device; + mock->obj_props.count = 0; + mock->plane.base.properties = &mock->obj_props; + mock->prop.base.id = 1; /* 0 is an invalid id */ + mock->prop.dev = &mock->device; + + drm_plane_enable_fb_damage_clips(&mock->plane); + + test->priv = mock; + + return 0; +} + +static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2, + int y2) +{ + state->src.x1 = x1; + state->src.y1 = y1; + state->src.x2 = x2; + state->src.y2 = y2; +} + +static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int x2, + int y2) +{ + r->x1 = x1; + r->y1 = y1; + r->x2 = x2; + r->y2 = y2; +} + +static void set_damage_blob(struct drm_property_blob *damage_blob, + struct drm_mode_rect *r, u32 size) +{ + damage_blob->length = size; + damage_blob->data = r; +} + +static void set_plane_damage(struct drm_plane_state *state, + struct drm_property_blob *damage_blob) +{ + state->fb_damage_clips = damage_blob; +} + +static void check_damage_clip(struct kunit *test, struct drm_rect *r, + int x1, int y1, int x2, int y2) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_plane_state state = mock->state; + + /* + * Round down x1/y1 and round up x2/y2. This is because damage is not in + * 16.16 fixed point so to catch all pixels. + */ + int src_x1 = state.src.x1 >> 16; + int src_y1 = state.src.y1 >> 16; + int src_x2 = (state.src.x2 >> 16) + !!(state.src.x2 & 0xFFFF); + int src_y2 = (state.src.y2 >> 16) + !!(state.src.y2 & 0xFFFF); + + if (x1 >= x2 || y1 >= y2) + KUNIT_FAIL(test, "Cannot have damage clip with no dimension."); + if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2) + KUNIT_FAIL(test, "Damage cannot be outside rounded plane src."); + if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2) + KUNIT_FAIL(test, "Damage = %d %d %d %d, want = %d %d %d %d", + r->x1, r->y1, r->x2, r->y2, x1, y1, x2, y2); +} + +static void igt_damage_iter_no_damage(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src same as fb size. */ + set_plane_src(&mock->old_state, 0, 0, mock->fb.width << 16, mock->fb.height << 16); + set_plane_src(&mock->state, 0, 0, mock->fb.width << 16, mock->fb.height << 16); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage."); + check_damage_clip(test, &clip, 0, 0, 2048, 2048); +} + +static void igt_damage_iter_no_damage_fractional_src(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src has fractional part. */ + set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe, + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); + set_plane_src(&mock->state, 0x3fffe, 0x3fffe, + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, + "Should return rounded off plane src as damage."); + check_damage_clip(test, &clip, 3, 3, 1028, 772); +} + +static void igt_damage_iter_no_damage_src_moved(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src moved since old plane state. */ + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 10 << 16, 10 << 16, + (10 + 1024) << 16, (10 + 768) << 16); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage."); + check_damage_clip(test, &clip, 10, 10, 1034, 778); +} + +static void igt_damage_iter_no_damage_fractional_src_moved(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src has fractional part and it moved since old plane state. */ + set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe, + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); + set_plane_src(&mock->state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage."); + check_damage_clip(test, &clip, 4, 4, 1029, 773); +} + +static void igt_damage_iter_no_damage_not_visible(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect clip; + u32 num_hits = 0; + + mock->state.visible = false; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); +} + +static void igt_damage_iter_no_damage_no_crtc(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect clip; + u32 num_hits = 0; + + mock->state.crtc = NULL; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); +} + +static void igt_damage_iter_no_damage_no_fb(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect clip; + u32 num_hits = 0; + + mock->state.fb = NULL; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); +} + +static void igt_damage_iter_simple_damage(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + /* Damage set to plane src */ + set_damage_clip(&damage, 0, 0, 1024, 768); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set."); + check_damage_clip(test, &clip, 0, 0, 1024, 768); +} + +static void igt_damage_iter_single_damage(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + set_damage_clip(&damage, 256, 192, 768, 576); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set."); + check_damage_clip(test, &clip, 256, 192, 768, 576); +} + +static void igt_damage_iter_single_damage_intersect_src(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + /* Damage intersect with plane src. */ + set_damage_clip(&damage, 256, 192, 1360, 768); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage clipped to src."); + check_damage_clip(test, &clip, 256, 192, 1024, 768); +} + +static void igt_damage_iter_single_damage_outside_src(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + /* Damage clip outside plane src */ + set_damage_clip(&damage, 1360, 1360, 1380, 1380); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); +} + +static void igt_damage_iter_single_damage_fractional_src(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src has fractional part. */ + set_plane_src(&mock->old_state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + set_plane_src(&mock->state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + set_damage_clip(&damage, 10, 10, 256, 330); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set."); + check_damage_clip(test, &clip, 10, 10, 256, 330); +} + +static void igt_damage_iter_single_damage_intersect_fractional_src(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src has fractional part. */ + set_plane_src(&mock->old_state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + set_plane_src(&mock->state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + /* Damage intersect with plane src. */ + set_damage_clip(&damage, 10, 1, 1360, 330); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, + "Should return damage clipped to rounded off src."); + check_damage_clip(test, &clip, 10, 4, 1029, 330); +} + +static void igt_damage_iter_single_damage_outside_fractional_src(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src has fractional part. */ + set_plane_src(&mock->old_state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + set_plane_src(&mock->state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + /* Damage clip outside plane src */ + set_damage_clip(&damage, 1360, 1360, 1380, 1380); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage."); +} + +static void igt_damage_iter_single_damage_src_moved(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src moved since old plane state. */ + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 10 << 16, 10 << 16, + (10 + 1024) << 16, (10 + 768) << 16); + set_damage_clip(&damage, 20, 30, 256, 256); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, + "Should return plane src as damage."); + check_damage_clip(test, &clip, 10, 10, 1034, 778); +} + +static void igt_damage_iter_single_damage_fractional_src_moved(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage; + struct drm_rect clip; + u32 num_hits = 0; + + /* Plane src with fractional part moved since old plane state. */ + set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe, + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); + set_plane_src(&mock->state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + /* Damage intersect with plane src. */ + set_damage_clip(&damage, 20, 30, 1360, 256); + set_damage_blob(&damage_blob, &damage, sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, + "Should return rounded off plane as damage."); + check_damage_clip(test, &clip, 4, 4, 1029, 773); +} + +static void igt_damage_iter_damage(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage[2]; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + /* 2 damage clips. */ + set_damage_clip(&damage[0], 20, 30, 200, 180); + set_damage_clip(&damage[1], 240, 200, 280, 250); + set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) { + if (num_hits == 0) + check_damage_clip(test, &clip, 20, 30, 200, 180); + if (num_hits == 1) + check_damage_clip(test, &clip, 240, 200, 280, 250); + num_hits++; + } + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set."); +} + +static void igt_damage_iter_damage_one_intersect(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage[2]; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + set_plane_src(&mock->state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + /* 2 damage clips, one intersect plane src. */ + set_damage_clip(&damage[0], 20, 30, 200, 180); + set_damage_clip(&damage[1], 2, 2, 1360, 1360); + set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) { + if (num_hits == 0) + check_damage_clip(test, &clip, 20, 30, 200, 180); + if (num_hits == 1) + check_damage_clip(test, &clip, 4, 4, 1029, 773); + num_hits++; + } + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set."); +} + +static void igt_damage_iter_damage_one_outside(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage[2]; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16); + set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16); + /* 2 damage clips, one outside plane src. */ + set_damage_clip(&damage[0], 1360, 1360, 1380, 1380); + set_damage_clip(&damage[1], 240, 200, 280, 250); + set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set."); + check_damage_clip(test, &clip, 240, 200, 280, 250); +} + +static void igt_damage_iter_damage_src_moved(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage[2]; + struct drm_rect clip; + u32 num_hits = 0; + + set_plane_src(&mock->old_state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + set_plane_src(&mock->state, 0x3fffe, 0x3fffe, + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); + /* 2 damage clips, one outside plane src. */ + set_damage_clip(&damage[0], 1360, 1360, 1380, 1380); + set_damage_clip(&damage[1], 240, 200, 280, 250); + set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, + "Should return round off plane src as damage."); + check_damage_clip(test, &clip, 3, 3, 1028, 772); +} + +static void igt_damage_iter_damage_not_visible(struct kunit *test) +{ + struct drm_damage_mock *mock = test->priv; + struct drm_atomic_helper_damage_iter iter; + struct drm_property_blob damage_blob; + struct drm_mode_rect damage[2]; + struct drm_rect clip; + u32 num_hits = 0; + + mock->state.visible = false; + + set_plane_src(&mock->old_state, 0x40002, 0x40002, + 0x40002 + (1024 << 16), 0x40002 + (768 << 16)); + set_plane_src(&mock->state, 0x3fffe, 0x3fffe, + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16)); + /* 2 damage clips, one outside plane src. */ + set_damage_clip(&damage[0], 1360, 1360, 1380, 1380); + set_damage_clip(&damage[1], 240, 200, 280, 250); + set_damage_blob(&damage_blob, &damage[0], sizeof(damage)); + set_plane_damage(&mock->state, &damage_blob); + drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state); + drm_atomic_for_each_plane_damage(&iter, &clip) + num_hits++; + + KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should not return any damage."); +} + +static struct kunit_case drm_damage_helper_tests[] = { + KUNIT_CASE(igt_damage_iter_no_damage), + KUNIT_CASE(igt_damage_iter_no_damage_fractional_src), + KUNIT_CASE(igt_damage_iter_no_damage_src_moved), + KUNIT_CASE(igt_damage_iter_no_damage_fractional_src_moved), + KUNIT_CASE(igt_damage_iter_no_damage_not_visible), + KUNIT_CASE(igt_damage_iter_no_damage_no_crtc), + KUNIT_CASE(igt_damage_iter_no_damage_no_fb), + KUNIT_CASE(igt_damage_iter_simple_damage), + KUNIT_CASE(igt_damage_iter_single_damage), + KUNIT_CASE(igt_damage_iter_single_damage_intersect_src), + KUNIT_CASE(igt_damage_iter_single_damage_outside_src), + KUNIT_CASE(igt_damage_iter_single_damage_fractional_src), + KUNIT_CASE(igt_damage_iter_single_damage_intersect_fractional_src), + KUNIT_CASE(igt_damage_iter_single_damage_outside_fractional_src), + KUNIT_CASE(igt_damage_iter_single_damage_src_moved), + KUNIT_CASE(igt_damage_iter_single_damage_fractional_src_moved), + KUNIT_CASE(igt_damage_iter_damage), + KUNIT_CASE(igt_damage_iter_damage_one_intersect), + KUNIT_CASE(igt_damage_iter_damage_one_outside), + KUNIT_CASE(igt_damage_iter_damage_src_moved), + KUNIT_CASE(igt_damage_iter_damage_not_visible), + { } +}; + +static struct kunit_suite drm_damage_helper_test_suite = { + .name = "drm_damage_helper", + .init = drm_damage_helper_init, + .test_cases = drm_damage_helper_tests, +}; + +kunit_test_suite(drm_damage_helper_test_suite); + +MODULE_LICENSE("GPL"); From 9f0527d22a52ff3470d8bf0dc79cf42c0677c23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:45 -0300 Subject: [PATCH 038/396] drm: selftest: convert drm_cmdline_parser selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM cmdline parser selftest to the KUnit API. Co-developed-by: Arthur Grillo <arthur.grillo@usp.br> Signed-off-by: Arthur Grillo <arthur.grillo@usp.br> Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-3-maira.canal@usp.br --- drivers/gpu/drm/selftests/Makefile | 2 +- .../gpu/drm/selftests/drm_cmdline_selftests.h | 68 - .../drm/selftests/test-drm_cmdline_parser.c | 1141 ----------------- drivers/gpu/drm/tests/Makefile | 3 +- .../gpu/drm/tests/drm_cmdline_parser_test.c | 1078 ++++++++++++++++ 5 files changed, 1081 insertions(+), 1211 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/drm_cmdline_selftests.h delete mode 100644 drivers/gpu/drm/selftests/test-drm_cmdline_parser.c create mode 100644 drivers/gpu/drm/tests/drm_cmdline_parser_test.c diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 7a1a732e0a1b..8633bb9ea717 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -3,5 +3,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \ test-drm_format.o test-drm_framebuffer.o \ test-drm_dp_mst_helper.o test-drm_rect.o -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \ +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \ test-drm_buddy.o diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h deleted file mode 100644 index 29e367db6118..000000000000 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* List each unit test as selftest(function) - * - * The name is used as both an enum and expanded as igt__name to create - * a module parameter. It must be unique and legal for a C identifier. - * - * Tests are executed in order by igt/drm_mm - */ - -#define cmdline_test(test) selftest(test, test) - -cmdline_test(drm_cmdline_test_force_d_only) -cmdline_test(drm_cmdline_test_force_D_only_dvi) -cmdline_test(drm_cmdline_test_force_D_only_hdmi) -cmdline_test(drm_cmdline_test_force_D_only_not_digital) -cmdline_test(drm_cmdline_test_force_e_only) -cmdline_test(drm_cmdline_test_margin_only) -cmdline_test(drm_cmdline_test_interlace_only) -cmdline_test(drm_cmdline_test_res) -cmdline_test(drm_cmdline_test_res_missing_x) -cmdline_test(drm_cmdline_test_res_missing_y) -cmdline_test(drm_cmdline_test_res_bad_y) -cmdline_test(drm_cmdline_test_res_missing_y_bpp) -cmdline_test(drm_cmdline_test_res_vesa) -cmdline_test(drm_cmdline_test_res_vesa_rblank) -cmdline_test(drm_cmdline_test_res_rblank) -cmdline_test(drm_cmdline_test_res_bpp) -cmdline_test(drm_cmdline_test_res_bad_bpp) -cmdline_test(drm_cmdline_test_res_refresh) -cmdline_test(drm_cmdline_test_res_bad_refresh) -cmdline_test(drm_cmdline_test_res_bpp_refresh) -cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced) -cmdline_test(drm_cmdline_test_res_bpp_refresh_margins) -cmdline_test(drm_cmdline_test_res_bpp_refresh_force_off) -cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_off) -cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on) -cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_analog) -cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_digital) -cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on) -cmdline_test(drm_cmdline_test_res_margins_force_on) -cmdline_test(drm_cmdline_test_res_vesa_margins) -cmdline_test(drm_cmdline_test_res_invalid_mode) -cmdline_test(drm_cmdline_test_res_bpp_wrong_place_mode) -cmdline_test(drm_cmdline_test_name) -cmdline_test(drm_cmdline_test_name_bpp) -cmdline_test(drm_cmdline_test_name_refresh) -cmdline_test(drm_cmdline_test_name_bpp_refresh) -cmdline_test(drm_cmdline_test_name_refresh_wrong_mode) -cmdline_test(drm_cmdline_test_name_refresh_invalid_mode) -cmdline_test(drm_cmdline_test_name_option) -cmdline_test(drm_cmdline_test_name_bpp_option) -cmdline_test(drm_cmdline_test_rotate_0) -cmdline_test(drm_cmdline_test_rotate_90) -cmdline_test(drm_cmdline_test_rotate_180) -cmdline_test(drm_cmdline_test_rotate_270) -cmdline_test(drm_cmdline_test_rotate_multiple) -cmdline_test(drm_cmdline_test_rotate_invalid_val) -cmdline_test(drm_cmdline_test_rotate_truncated) -cmdline_test(drm_cmdline_test_hmirror) -cmdline_test(drm_cmdline_test_vmirror) -cmdline_test(drm_cmdline_test_margin_options) -cmdline_test(drm_cmdline_test_multiple_options) -cmdline_test(drm_cmdline_test_invalid_option) -cmdline_test(drm_cmdline_test_bpp_extra_and_option) -cmdline_test(drm_cmdline_test_extra_and_option) -cmdline_test(drm_cmdline_test_freestanding_options) -cmdline_test(drm_cmdline_test_freestanding_force_e_and_options) -cmdline_test(drm_cmdline_test_panel_orientation) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c deleted file mode 100644 index d96cd890def6..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ /dev/null @@ -1,1141 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2019 Bootlin - */ - -#define pr_fmt(fmt) "drm_cmdline: " fmt - -#include <linux/kernel.h> -#include <linux/module.h> - -#include <drm/drm_connector.h> -#include <drm/drm_modes.h> - -#define TESTS "drm_cmdline_selftests.h" -#include "drm_selftest.h" -#include "test-drm_modeset_common.h" - -static const struct drm_connector no_connector = {}; - -static int drm_cmdline_test_force_e_only(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("e", - &no_connector, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_force_D_only_not_digital(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("D", - &no_connector, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static const struct drm_connector connector_hdmi = { - .connector_type = DRM_MODE_CONNECTOR_HDMIB, -}; - -static int drm_cmdline_test_force_D_only_hdmi(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("D", - &connector_hdmi, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL); - - return 0; -} - -static const struct drm_connector connector_dvi = { - .connector_type = DRM_MODE_CONNECTOR_DVII, -}; - -static int drm_cmdline_test_force_D_only_dvi(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("D", - &connector_dvi, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL); - - return 0; -} - -static int drm_cmdline_test_force_d_only(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("d", - &no_connector, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_OFF); - - return 0; -} - -static int drm_cmdline_test_margin_only(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("m", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_interlace_only(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("i", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_missing_x(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("x480", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_missing_y(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("1024x", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_bad_y(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("1024xtest", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_missing_y_bpp(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("1024x-24", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_vesa(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480M", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(!mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_vesa_rblank(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480MR", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(!mode.rb); - FAIL_ON(!mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_rblank(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480R", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(!mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_bpp(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_bad_bpp(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480-test", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_refresh(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480@60", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_bad_refresh(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480@refresh", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_interlaced(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60i", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(!mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_margins(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60m", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(!mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_force_off(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60d", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_OFF); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_force_on_off(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480-24@60de", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_force_on(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60e", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_force_on_analog(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60D", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_force_on_digital(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - static const struct drm_connector connector = { - .connector_type = DRM_MODE_CONNECTOR_DVII, - }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60D", - &connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL); - - return 0; -} - -static int drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60ime", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(!mode.refresh_specified); - FAIL_ON(mode.refresh != 60); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(!mode.interlace); - FAIL_ON(!mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_res_margins_force_on(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480me", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(!mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_res_vesa_margins(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480Mm", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(!mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(!mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_res_invalid_mode(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480f", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_res_bpp_wrong_place_mode(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480e-24", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_name(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC", - &no_connector, - &mode)); - FAIL_ON(strcmp(mode.name, "NTSC")); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - return 0; -} - -static int drm_cmdline_test_name_bpp(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC-24", - &no_connector, - &mode)); - FAIL_ON(strcmp(mode.name, "NTSC")); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - return 0; -} - -static int drm_cmdline_test_name_bpp_refresh(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC-24@60", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_name_refresh(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_name_refresh_wrong_mode(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60m", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_name_refresh_invalid_mode(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60f", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_name_option(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC,rotate=180", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(strcmp(mode.name, "NTSC")); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180); - - return 0; -} - -static int drm_cmdline_test_name_bpp_option(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC-24,rotate=180", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(strcmp(mode.name, "NTSC")); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180); - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - return 0; -} - -static int drm_cmdline_test_rotate_0(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=0", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_0); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_rotate_90(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=90", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_90); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_rotate_180(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=180", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_rotate_270(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=270", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_270); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_rotate_multiple(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=0,rotate=90", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_rotate_invalid_val(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=42", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_rotate_truncated(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_hmirror(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,reflect_x", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X)); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_vmirror(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,reflect_y", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y)); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_margin_options(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.tv_margins.right != 14); - FAIL_ON(mode.tv_margins.left != 24); - FAIL_ON(mode.tv_margins.bottom != 36); - FAIL_ON(mode.tv_margins.top != 42); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_multiple_options(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=270,reflect_x", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X)); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_invalid_option(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,test=42", - &no_connector, - &mode)); - - return 0; -} - -static int drm_cmdline_test_bpp_extra_and_option(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24e,rotate=180", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180); - - FAIL_ON(mode.refresh_specified); - - FAIL_ON(!mode.bpp_specified); - FAIL_ON(mode.bpp != 24); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_extra_and_option(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480e,rotate=180", - &no_connector, - &mode)); - FAIL_ON(!mode.specified); - FAIL_ON(mode.xres != 720); - FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180); - - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_freestanding_options(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("margin_right=14,margin_left=24,margin_bottom=36,margin_top=42", - &no_connector, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.tv_margins.right != 14); - FAIL_ON(mode.tv_margins.left != 24); - FAIL_ON(mode.tv_margins.bottom != 36); - FAIL_ON(mode.tv_margins.top != 42); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42", - &no_connector, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.tv_margins.right != 14); - FAIL_ON(mode.tv_margins.left != 24); - FAIL_ON(mode.tv_margins.bottom != 36); - FAIL_ON(mode.tv_margins.top != 42); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_ON); - - return 0; -} - -static int drm_cmdline_test_panel_orientation(void *ignored) -{ - struct drm_cmdline_mode mode = { }; - - FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down", - &no_connector, - &mode)); - FAIL_ON(mode.specified); - FAIL_ON(mode.refresh_specified); - FAIL_ON(mode.bpp_specified); - - FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP); - - FAIL_ON(mode.rb); - FAIL_ON(mode.cvt); - FAIL_ON(mode.interlace); - FAIL_ON(mode.margins); - FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); - - return 0; -} - -#include "drm_selftest.c" - -static int __init test_drm_cmdline_init(void) -{ - int err; - - err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL); - - return err > 0 ? 0 : err; -} -module_init(test_drm_cmdline_init); - -MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 2f399e03d50c..b3e73d674c67 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o +obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ + drm_cmdline_parser_test.o diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c new file mode 100644 index 000000000000..59b29cdfdd35 --- /dev/null +++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c @@ -0,0 +1,1078 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Bootlin + * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> + */ + +#include <kunit/test.h> + +#include <drm/drm_connector.h> +#include <drm/drm_modes.h> + +static const struct drm_connector no_connector = {}; + +static void drm_cmdline_test_force_e_only(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "e"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_force_D_only_not_digital(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "D"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static const struct drm_connector connector_hdmi = { + .connector_type = DRM_MODE_CONNECTOR_HDMIB, +}; + +static void drm_cmdline_test_force_D_only_hdmi(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "D"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &connector_hdmi, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL); +} + +static const struct drm_connector connector_dvi = { + .connector_type = DRM_MODE_CONNECTOR_DVII, +}; + +static void drm_cmdline_test_force_D_only_dvi(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "D"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &connector_dvi, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL); +} + +static void drm_cmdline_test_force_d_only(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "d"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF); +} + +static void drm_cmdline_test_margin_only(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "m"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_interlace_only(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "i"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_missing_x(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "x480"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_missing_y(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "1024x"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_bad_y(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "1024xtest"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_missing_y_bpp(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "1024x-24"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_vesa(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480M"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_TRUE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_vesa_rblank(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480MR"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_TRUE(test, mode.rb); + KUNIT_EXPECT_TRUE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_rblank(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480R"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_TRUE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_bpp(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_bad_bpp(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-test"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_refresh(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480@60"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_bad_refresh(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480@refresh"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_bpp_refresh(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_bpp_refresh_interlaced(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60i"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_TRUE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_bpp_refresh_margins(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60m"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_TRUE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_bpp_refresh_force_off(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60d"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF); +} + +static void drm_cmdline_test_res_bpp_refresh_force_on_off(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60de"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_bpp_refresh_force_on(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60e"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_res_bpp_refresh_force_on_analog(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60D"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_res_bpp_refresh_force_on_digital(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + static const struct drm_connector connector = { + .connector_type = DRM_MODE_CONNECTOR_DVII, + }; + const char *cmdline = "720x480-24@60D"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL); +} + +static void drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24@60ime"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_TRUE(test, mode.refresh_specified); + KUNIT_EXPECT_EQ(test, mode.refresh, 60); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_TRUE(test, mode.interlace); + KUNIT_EXPECT_TRUE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_res_margins_force_on(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480me"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_TRUE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_res_vesa_margins(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480Mm"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_TRUE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_TRUE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_res_invalid_mode(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480f"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_res_bpp_wrong_place_mode(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480e-24"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_name(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); +} + +static void drm_cmdline_test_name_bpp(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC-24"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); +} + +static void drm_cmdline_test_name_bpp_refresh(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC-24@60"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_name_refresh(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC@60"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_name_refresh_wrong_mode(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC@60m"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_name_refresh_invalid_mode(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC@60f"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_name_option(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC,rotate=180"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180); +} + +static void drm_cmdline_test_name_bpp_option(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "NTSC-24,rotate=180"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180); + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); +} + +static void drm_cmdline_test_rotate_0(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate=0"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_0); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_rotate_90(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate=90"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_90); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_rotate_180(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate=180"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_rotate_270(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate=270"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_270); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_rotate_multiple(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate=0,rotate=90"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_rotate_invalid_val(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate=42"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_rotate_truncated(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate="; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_hmirror(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,reflect_x"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X)); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_vmirror(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,reflect_y"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y)); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_margin_options(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = + "720x480,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.tv_margins.right, 14); + KUNIT_EXPECT_EQ(test, mode.tv_margins.left, 24); + KUNIT_EXPECT_EQ(test, mode.tv_margins.bottom, 36); + KUNIT_EXPECT_EQ(test, mode.tv_margins.top, 42); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_multiple_options(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,rotate=270,reflect_x"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, (DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X)); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_invalid_option(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480,test=42"; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); +} + +static void drm_cmdline_test_bpp_extra_and_option(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480-24e,rotate=180"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_TRUE(test, mode.bpp_specified); + KUNIT_EXPECT_EQ(test, mode.bpp, 24); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_extra_and_option(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "720x480e,rotate=180"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, 720); + KUNIT_EXPECT_EQ(test, mode.yres, 480); + KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_freestanding_options(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_EQ(test, mode.tv_margins.right, 14); + KUNIT_EXPECT_EQ(test, mode.tv_margins.left, 24); + KUNIT_EXPECT_EQ(test, mode.tv_margins.bottom, 36); + KUNIT_EXPECT_EQ(test, mode.tv_margins.top, 42); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static void drm_cmdline_test_freestanding_force_e_and_options(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_EQ(test, mode.tv_margins.right, 14); + KUNIT_EXPECT_EQ(test, mode.tv_margins.left, 24); + KUNIT_EXPECT_EQ(test, mode.tv_margins.bottom, 36); + KUNIT_EXPECT_EQ(test, mode.tv_margins.top, 42); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON); +} + +static void drm_cmdline_test_panel_orientation(struct kunit *test) +{ + struct drm_cmdline_mode mode = { }; + const char *cmdline = "panel_orientation=upside_down"; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_FALSE(test, mode.specified); + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_EQ(test, mode.panel_orientation, DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_FALSE(test, mode.interlace); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +static struct kunit_case drm_cmdline_parser_tests[] = { + KUNIT_CASE(drm_cmdline_test_force_d_only), + KUNIT_CASE(drm_cmdline_test_force_D_only_dvi), + KUNIT_CASE(drm_cmdline_test_force_D_only_hdmi), + KUNIT_CASE(drm_cmdline_test_force_D_only_not_digital), + KUNIT_CASE(drm_cmdline_test_force_e_only), + KUNIT_CASE(drm_cmdline_test_margin_only), + KUNIT_CASE(drm_cmdline_test_interlace_only), + KUNIT_CASE(drm_cmdline_test_res), + KUNIT_CASE(drm_cmdline_test_res_missing_x), + KUNIT_CASE(drm_cmdline_test_res_missing_y), + KUNIT_CASE(drm_cmdline_test_res_bad_y), + KUNIT_CASE(drm_cmdline_test_res_missing_y_bpp), + KUNIT_CASE(drm_cmdline_test_res_vesa), + KUNIT_CASE(drm_cmdline_test_res_vesa_rblank), + KUNIT_CASE(drm_cmdline_test_res_rblank), + KUNIT_CASE(drm_cmdline_test_res_bpp), + KUNIT_CASE(drm_cmdline_test_res_bad_bpp), + KUNIT_CASE(drm_cmdline_test_res_refresh), + KUNIT_CASE(drm_cmdline_test_res_bad_refresh), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_margins), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_off), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_off), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_analog), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_digital), + KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on), + KUNIT_CASE(drm_cmdline_test_res_margins_force_on), + KUNIT_CASE(drm_cmdline_test_res_vesa_margins), + KUNIT_CASE(drm_cmdline_test_res_invalid_mode), + KUNIT_CASE(drm_cmdline_test_res_bpp_wrong_place_mode), + KUNIT_CASE(drm_cmdline_test_name), + KUNIT_CASE(drm_cmdline_test_name_bpp), + KUNIT_CASE(drm_cmdline_test_name_refresh), + KUNIT_CASE(drm_cmdline_test_name_bpp_refresh), + KUNIT_CASE(drm_cmdline_test_name_refresh_wrong_mode), + KUNIT_CASE(drm_cmdline_test_name_refresh_invalid_mode), + KUNIT_CASE(drm_cmdline_test_name_option), + KUNIT_CASE(drm_cmdline_test_name_bpp_option), + KUNIT_CASE(drm_cmdline_test_rotate_0), + KUNIT_CASE(drm_cmdline_test_rotate_90), + KUNIT_CASE(drm_cmdline_test_rotate_180), + KUNIT_CASE(drm_cmdline_test_rotate_270), + KUNIT_CASE(drm_cmdline_test_rotate_multiple), + KUNIT_CASE(drm_cmdline_test_rotate_invalid_val), + KUNIT_CASE(drm_cmdline_test_rotate_truncated), + KUNIT_CASE(drm_cmdline_test_hmirror), + KUNIT_CASE(drm_cmdline_test_vmirror), + KUNIT_CASE(drm_cmdline_test_margin_options), + KUNIT_CASE(drm_cmdline_test_multiple_options), + KUNIT_CASE(drm_cmdline_test_invalid_option), + KUNIT_CASE(drm_cmdline_test_bpp_extra_and_option), + KUNIT_CASE(drm_cmdline_test_extra_and_option), + KUNIT_CASE(drm_cmdline_test_freestanding_options), + KUNIT_CASE(drm_cmdline_test_freestanding_force_e_and_options), + KUNIT_CASE(drm_cmdline_test_panel_orientation), + {} +}; + +static struct kunit_suite drm_cmdline_parser_test_suite = { + .name = "drm_cmdline_parser", + .test_cases = drm_cmdline_parser_tests +}; + +kunit_test_suite(drm_cmdline_parser_test_suite); + +MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>"); +MODULE_LICENSE("GPL"); From 93de485cd822d429e91f197a820f02ee57d38fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:46 -0300 Subject: [PATCH 039/396] drm: selftest: convert drm_rect selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM rect selftest to the KUnit API. Co-developed-by: Carlos Veras <carlos.craveiro@usp.br> Signed-off-by: Carlos Veras <carlos.craveiro@usp.br> Co-developed-by: Matheus Vieira <matheus.vieira.g@usp.br> Signed-off-by: Matheus Vieira <matheus.vieira.g@usp.br> Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-4-maira.canal@usp.br --- drivers/gpu/drm/selftests/Makefile | 2 +- .../gpu/drm/selftests/drm_modeset_selftests.h | 4 - .../drm/selftests/test-drm_modeset_common.h | 4 - drivers/gpu/drm/selftests/test-drm_rect.c | 223 ------------------ drivers/gpu/drm/tests/Makefile | 2 +- drivers/gpu/drm/tests/drm_rect_test.c | 214 +++++++++++++++++ 6 files changed, 216 insertions(+), 233 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/test-drm_rect.c create mode 100644 drivers/gpu/drm/tests/drm_rect_test.c diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 8633bb9ea717..8a794914e328 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \ test-drm_format.o test-drm_framebuffer.o \ - test-drm_dp_mst_helper.o test-drm_rect.o + test-drm_dp_mst_helper.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \ test-drm_buddy.o diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h index 4787b3b70709..a3ca90307364 100644 --- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h +++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h @@ -6,10 +6,6 @@ * * Tests are executed in order by igt/drm_selftests_helper */ -selftest(drm_rect_clip_scaled_div_by_zero, igt_drm_rect_clip_scaled_div_by_zero) -selftest(drm_rect_clip_scaled_not_clipped, igt_drm_rect_clip_scaled_not_clipped) -selftest(drm_rect_clip_scaled_clipped, igt_drm_rect_clip_scaled_clipped) -selftest(drm_rect_clip_scaled_signed_vs_unsigned, igt_drm_rect_clip_scaled_signed_vs_unsigned) selftest(check_plane_state, igt_check_plane_state) selftest(check_drm_format_block_width, igt_check_drm_format_block_width) selftest(check_drm_format_block_height, igt_check_drm_format_block_height) diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h index c29354e59cec..42a10d7da51c 100644 --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h +++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h @@ -16,10 +16,6 @@ #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n") -int igt_drm_rect_clip_scaled_div_by_zero(void *ignored); -int igt_drm_rect_clip_scaled_not_clipped(void *ignored); -int igt_drm_rect_clip_scaled_clipped(void *ignored); -int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored); int igt_check_plane_state(void *ignored); int igt_check_drm_format_block_width(void *ignored); int igt_check_drm_format_block_height(void *ignored); diff --git a/drivers/gpu/drm/selftests/test-drm_rect.c b/drivers/gpu/drm/selftests/test-drm_rect.c deleted file mode 100644 index 3a5ff38321f4..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_rect.c +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Test cases for the drm_rect functions - */ - -#define pr_fmt(fmt) "drm_rect: " fmt - -#include <linux/limits.h> - -#include <drm/drm_rect.h> - -#include "test-drm_modeset_common.h" - -int igt_drm_rect_clip_scaled_div_by_zero(void *ignored) -{ - struct drm_rect src, dst, clip; - bool visible; - - /* - * Make sure we don't divide by zero when dst - * width/height is zero and dst and clip do not intersect. - */ - drm_rect_init(&src, 0, 0, 0, 0); - drm_rect_init(&dst, 0, 0, 0, 0); - drm_rect_init(&clip, 1, 1, 1, 1); - visible = drm_rect_clip_scaled(&src, &dst, &clip); - FAIL(visible, "Destination not be visible\n"); - FAIL(drm_rect_visible(&src), "Source should not be visible\n"); - - drm_rect_init(&src, 0, 0, 0, 0); - drm_rect_init(&dst, 3, 3, 0, 0); - drm_rect_init(&clip, 1, 1, 1, 1); - visible = drm_rect_clip_scaled(&src, &dst, &clip); - FAIL(visible, "Destination not be visible\n"); - FAIL(drm_rect_visible(&src), "Source should not be visible\n"); - - return 0; -} - -int igt_drm_rect_clip_scaled_not_clipped(void *ignored) -{ - struct drm_rect src, dst, clip; - bool visible; - - /* 1:1 scaling */ - drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16); - drm_rect_init(&dst, 0, 0, 1, 1); - drm_rect_init(&clip, 0, 0, 1, 1); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 0 || src.x2 != 1 << 16 || - src.y1 != 0 || src.y2 != 1 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 0 || dst.x2 != 1 || - dst.y1 != 0 || dst.y2 != 1, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - /* 2:1 scaling */ - drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); - drm_rect_init(&dst, 0, 0, 1, 1); - drm_rect_init(&clip, 0, 0, 1, 1); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 0 || src.x2 != 2 << 16 || - src.y1 != 0 || src.y2 != 2 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 0 || dst.x2 != 1 || - dst.y1 != 0 || dst.y2 != 1, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - /* 1:2 scaling */ - drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16); - drm_rect_init(&dst, 0, 0, 2, 2); - drm_rect_init(&clip, 0, 0, 2, 2); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 0 || src.x2 != 1 << 16 || - src.y1 != 0 || src.y2 != 1 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 0 || dst.x2 != 2 || - dst.y1 != 0 || dst.y2 != 2, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - return 0; -} - -int igt_drm_rect_clip_scaled_clipped(void *ignored) -{ - struct drm_rect src, dst, clip; - bool visible; - - /* 1:1 scaling top/left clip */ - drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); - drm_rect_init(&dst, 0, 0, 2, 2); - drm_rect_init(&clip, 0, 0, 1, 1); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 0 || src.x2 != 1 << 16 || - src.y1 != 0 || src.y2 != 1 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 0 || dst.x2 != 1 || - dst.y1 != 0 || dst.y2 != 1, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - /* 1:1 scaling bottom/right clip */ - drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); - drm_rect_init(&dst, 0, 0, 2, 2); - drm_rect_init(&clip, 1, 1, 1, 1); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 || - src.y1 != 1 << 16 || src.y2 != 2 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 1 || dst.x2 != 2 || - dst.y1 != 1 || dst.y2 != 2, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - /* 2:1 scaling top/left clip */ - drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16); - drm_rect_init(&dst, 0, 0, 2, 2); - drm_rect_init(&clip, 0, 0, 1, 1); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 0 || src.x2 != 2 << 16 || - src.y1 != 0 || src.y2 != 2 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 0 || dst.x2 != 1 || - dst.y1 != 0 || dst.y2 != 1, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - /* 2:1 scaling bottom/right clip */ - drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16); - drm_rect_init(&dst, 0, 0, 2, 2); - drm_rect_init(&clip, 1, 1, 1, 1); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 2 << 16 || src.x2 != 4 << 16 || - src.y1 != 2 << 16 || src.y2 != 4 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 1 || dst.x2 != 2 || - dst.y1 != 1 || dst.y2 != 2, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - /* 1:2 scaling top/left clip */ - drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); - drm_rect_init(&dst, 0, 0, 4, 4); - drm_rect_init(&clip, 0, 0, 2, 2); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 0 || src.x2 != 1 << 16 || - src.y1 != 0 || src.y2 != 1 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 0 || dst.x2 != 2 || - dst.y1 != 0 || dst.y2 != 2, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - /* 1:2 scaling bottom/right clip */ - drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); - drm_rect_init(&dst, 0, 0, 4, 4); - drm_rect_init(&clip, 2, 2, 2, 2); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 || - src.y1 != 1 << 16 || src.y2 != 2 << 16, - "Source badly clipped\n"); - FAIL(dst.x1 != 2 || dst.x2 != 4 || - dst.y1 != 2 || dst.y2 != 4, - "Destination badly clipped\n"); - FAIL(!visible, "Destination should be visible\n"); - FAIL(!drm_rect_visible(&src), "Source should be visible\n"); - - return 0; -} - -int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored) -{ - struct drm_rect src, dst, clip; - bool visible; - - /* - * 'clip.x2 - dst.x1 >= dst width' could result a negative - * src rectangle width which is no longer expected by the - * code as it's using unsigned types. This could lead to - * the clipped source rectangle appering visible when it - * should have been fully clipped. Make sure both rectangles - * end up invisible. - */ - drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX); - drm_rect_init(&dst, 0, 0, 2, 2); - drm_rect_init(&clip, 3, 3, 1, 1); - - visible = drm_rect_clip_scaled(&src, &dst, &clip); - - FAIL(visible, "Destination should not be visible\n"); - FAIL(drm_rect_visible(&src), "Source should not be visible\n"); - - return 0; -} diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index b3e73d674c67..f2eced30a955 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ - drm_cmdline_parser_test.o + drm_cmdline_parser_test.o drm_rect_test.o diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c new file mode 100644 index 000000000000..c1dbefd49a4c --- /dev/null +++ b/drivers/gpu/drm/tests/drm_rect_test.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test cases for the drm_rect functions + * + * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> + */ + +#include <kunit/test.h> + +#include <drm/drm_rect.h> + +static void igt_drm_rect_clip_scaled_div_by_zero(struct kunit *test) +{ + struct drm_rect src, dst, clip; + bool visible; + + /* + * Make sure we don't divide by zero when dst + * width/height is zero and dst and clip do not intersect. + */ + drm_rect_init(&src, 0, 0, 0, 0); + drm_rect_init(&dst, 0, 0, 0, 0); + drm_rect_init(&clip, 1, 1, 1, 1); + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n"); + KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n"); + + drm_rect_init(&src, 0, 0, 0, 0); + drm_rect_init(&dst, 3, 3, 0, 0); + drm_rect_init(&clip, 1, 1, 1, 1); + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n"); + KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n"); +} + +static void igt_drm_rect_clip_scaled_not_clipped(struct kunit *test) +{ + struct drm_rect src, dst, clip; + bool visible; + + /* 1:1 scaling */ + drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16); + drm_rect_init(&dst, 0, 0, 1, 1); + drm_rect_init(&clip, 0, 0, 1, 1); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || + src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || + dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); + + /* 2:1 scaling */ + drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); + drm_rect_init(&dst, 0, 0, 1, 1); + drm_rect_init(&clip, 0, 0, 1, 1); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 || + src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || + dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); + + /* 1:2 scaling */ + drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16); + drm_rect_init(&dst, 0, 0, 2, 2); + drm_rect_init(&clip, 0, 0, 2, 2); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || + src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || + dst.y1 != 0 || dst.y2 != 2, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); +} + +static void igt_drm_rect_clip_scaled_clipped(struct kunit *test) +{ + struct drm_rect src, dst, clip; + bool visible; + + /* 1:1 scaling top/left clip */ + drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); + drm_rect_init(&dst, 0, 0, 2, 2); + drm_rect_init(&clip, 0, 0, 1, 1); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || + src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || + dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); + + /* 1:1 scaling bottom/right clip */ + drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); + drm_rect_init(&dst, 0, 0, 2, 2); + drm_rect_init(&clip, 1, 1, 1, 1); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 || + src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 || + dst.y2 != 2, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); + + /* 2:1 scaling top/left clip */ + drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16); + drm_rect_init(&dst, 0, 0, 2, 2); + drm_rect_init(&clip, 0, 0, 1, 1); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 || + src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || dst.y1 != 0 || + dst.y2 != 1, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); + + /* 2:1 scaling bottom/right clip */ + drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16); + drm_rect_init(&dst, 0, 0, 2, 2); + drm_rect_init(&clip, 1, 1, 1, 1); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 2 << 16 || src.x2 != 4 << 16 || + src.y1 != 2 << 16 || src.y2 != 4 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 || + dst.y2 != 2, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); + + /* 1:2 scaling top/left clip */ + drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); + drm_rect_init(&dst, 0, 0, 4, 4); + drm_rect_init(&clip, 0, 0, 2, 2); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || + src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || dst.y1 != 0 || + dst.y2 != 2, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); + + /* 1:2 scaling bottom/right clip */ + drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); + drm_rect_init(&dst, 0, 0, 4, 4); + drm_rect_init(&clip, 2, 2, 2, 2); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 || + src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n"); + KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 2 || dst.x2 != 4 || dst.y1 != 2 || + dst.y2 != 4, "Destination badly clipped\n"); + KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); + KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); +} + +static void igt_drm_rect_clip_scaled_signed_vs_unsigned(struct kunit *test) +{ + struct drm_rect src, dst, clip; + bool visible; + + /* + * 'clip.x2 - dst.x1 >= dst width' could result a negative + * src rectangle width which is no longer expected by the + * code as it's using unsigned types. This could lead to + * the clipped source rectangle appering visible when it + * should have been fully clipped. Make sure both rectangles + * end up invisible. + */ + drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX); + drm_rect_init(&dst, 0, 0, 2, 2); + drm_rect_init(&clip, 3, 3, 1, 1); + + visible = drm_rect_clip_scaled(&src, &dst, &clip); + + KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination should not be visible\n"); + KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n"); +} + +static struct kunit_case drm_rect_tests[] = { + KUNIT_CASE(igt_drm_rect_clip_scaled_div_by_zero), + KUNIT_CASE(igt_drm_rect_clip_scaled_not_clipped), + KUNIT_CASE(igt_drm_rect_clip_scaled_clipped), + KUNIT_CASE(igt_drm_rect_clip_scaled_signed_vs_unsigned), + { } +}; + +static struct kunit_suite drm_rect_test_suite = { + .name = "drm_rect", + .test_cases = drm_rect_tests, +}; + +kunit_test_suite(drm_rect_test_suite); + +MODULE_LICENSE("GPL"); From 0421bb0baa84fc93bbb659fe682e19266730f9f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:47 -0300 Subject: [PATCH 040/396] drm: selftest: convert drm_format selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM format selftest to the KUnit API. Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-5-maira.canal@usp.br --- drivers/gpu/drm/selftests/Makefile | 3 +- .../gpu/drm/selftests/drm_modeset_selftests.h | 3 - drivers/gpu/drm/selftests/test-drm_format.c | 280 ----------------- .../drm/selftests/test-drm_modeset_common.h | 3 - drivers/gpu/drm/tests/Makefile | 2 +- drivers/gpu/drm/tests/drm_format_test.c | 287 ++++++++++++++++++ 6 files changed, 289 insertions(+), 289 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c create mode 100644 drivers/gpu/drm/tests/drm_format_test.c diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 8a794914e328..b7f252d886d0 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \ - test-drm_format.o test-drm_framebuffer.o \ - test-drm_dp_mst_helper.o + test-drm_framebuffer.o test-drm_dp_mst_helper.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \ test-drm_buddy.o diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h index a3ca90307364..63061ef55eff 100644 --- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h +++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h @@ -7,9 +7,6 @@ * Tests are executed in order by igt/drm_selftests_helper */ selftest(check_plane_state, igt_check_plane_state) -selftest(check_drm_format_block_width, igt_check_drm_format_block_width) -selftest(check_drm_format_block_height, igt_check_drm_format_block_height) -selftest(check_drm_format_min_pitch, igt_check_drm_format_min_pitch) selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create) selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode) selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode) diff --git a/drivers/gpu/drm/selftests/test-drm_format.c b/drivers/gpu/drm/selftests/test-drm_format.c deleted file mode 100644 index c5e212afa27a..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_format.c +++ /dev/null @@ -1,280 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Test cases for the drm_format functions - */ - -#define pr_fmt(fmt) "drm_format: " fmt - -#include <linux/errno.h> -#include <linux/kernel.h> - -#include <drm/drm_fourcc.h> - -#include "test-drm_modeset_common.h" - -int igt_check_drm_format_block_width(void *ignored) -{ - const struct drm_format_info *info = NULL; - - /* Test invalid arguments */ - FAIL_ON(drm_format_info_block_width(info, 0) != 0); - FAIL_ON(drm_format_info_block_width(info, -1) != 0); - FAIL_ON(drm_format_info_block_width(info, 1) != 0); - - /* Test 1 plane format */ - info = drm_format_info(DRM_FORMAT_XRGB4444); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_width(info, 0) != 1); - FAIL_ON(drm_format_info_block_width(info, 1) != 0); - FAIL_ON(drm_format_info_block_width(info, -1) != 0); - - /* Test 2 planes format */ - info = drm_format_info(DRM_FORMAT_NV12); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_width(info, 0) != 1); - FAIL_ON(drm_format_info_block_width(info, 1) != 1); - FAIL_ON(drm_format_info_block_width(info, 2) != 0); - FAIL_ON(drm_format_info_block_width(info, -1) != 0); - - /* Test 3 planes format */ - info = drm_format_info(DRM_FORMAT_YUV422); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_width(info, 0) != 1); - FAIL_ON(drm_format_info_block_width(info, 1) != 1); - FAIL_ON(drm_format_info_block_width(info, 2) != 1); - FAIL_ON(drm_format_info_block_width(info, 3) != 0); - FAIL_ON(drm_format_info_block_width(info, -1) != 0); - - /* Test a tiled format */ - info = drm_format_info(DRM_FORMAT_X0L0); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_width(info, 0) != 2); - FAIL_ON(drm_format_info_block_width(info, 1) != 0); - FAIL_ON(drm_format_info_block_width(info, -1) != 0); - - return 0; -} - -int igt_check_drm_format_block_height(void *ignored) -{ - const struct drm_format_info *info = NULL; - - /* Test invalid arguments */ - FAIL_ON(drm_format_info_block_height(info, 0) != 0); - FAIL_ON(drm_format_info_block_height(info, -1) != 0); - FAIL_ON(drm_format_info_block_height(info, 1) != 0); - - /* Test 1 plane format */ - info = drm_format_info(DRM_FORMAT_XRGB4444); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_height(info, 0) != 1); - FAIL_ON(drm_format_info_block_height(info, 1) != 0); - FAIL_ON(drm_format_info_block_height(info, -1) != 0); - - /* Test 2 planes format */ - info = drm_format_info(DRM_FORMAT_NV12); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_height(info, 0) != 1); - FAIL_ON(drm_format_info_block_height(info, 1) != 1); - FAIL_ON(drm_format_info_block_height(info, 2) != 0); - FAIL_ON(drm_format_info_block_height(info, -1) != 0); - - /* Test 3 planes format */ - info = drm_format_info(DRM_FORMAT_YUV422); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_height(info, 0) != 1); - FAIL_ON(drm_format_info_block_height(info, 1) != 1); - FAIL_ON(drm_format_info_block_height(info, 2) != 1); - FAIL_ON(drm_format_info_block_height(info, 3) != 0); - FAIL_ON(drm_format_info_block_height(info, -1) != 0); - - /* Test a tiled format */ - info = drm_format_info(DRM_FORMAT_X0L0); - FAIL_ON(!info); - FAIL_ON(drm_format_info_block_height(info, 0) != 2); - FAIL_ON(drm_format_info_block_height(info, 1) != 0); - FAIL_ON(drm_format_info_block_height(info, -1) != 0); - - return 0; -} - -int igt_check_drm_format_min_pitch(void *ignored) -{ - const struct drm_format_info *info = NULL; - - /* Test invalid arguments */ - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - - /* Test 1 plane 8 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_RGB332); - FAIL_ON(!info); - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - - FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1); - FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920); - FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096); - FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) != - (uint64_t)UINT_MAX); - FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) != - (uint64_t)(UINT_MAX - 1)); - - /* Test 1 plane 16 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_XRGB4444); - FAIL_ON(!info); - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - - FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 4); - FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1280); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 2048); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 3840); - FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 8192); - FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 1342); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) != - (uint64_t)UINT_MAX * 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) != - (uint64_t)(UINT_MAX - 1) * 2); - - /* Test 1 plane 24 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_RGB888); - FAIL_ON(!info); - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - - FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 3); - FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 6); - FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1920); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 3072); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 5760); - FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 12288); - FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 2013); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) != - (uint64_t)UINT_MAX * 3); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) != - (uint64_t)(UINT_MAX - 1) * 3); - - /* Test 1 plane 32 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_ABGR8888); - FAIL_ON(!info); - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - - FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 4); - FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 8); - FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 2560); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 4096); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 7680); - FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 16384); - FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 2684); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) != - (uint64_t)UINT_MAX * 4); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) != - (uint64_t)(UINT_MAX - 1) * 4); - - /* Test 2 planes format */ - info = drm_format_info(DRM_FORMAT_NV12); - FAIL_ON(!info); - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 2, 0) != 0); - - FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1); - FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640); - FAIL_ON(drm_format_info_min_pitch(info, 1, 320) != 640); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024); - FAIL_ON(drm_format_info_min_pitch(info, 1, 512) != 1024); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920); - FAIL_ON(drm_format_info_min_pitch(info, 1, 960) != 1920); - FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096); - FAIL_ON(drm_format_info_min_pitch(info, 1, 2048) != 4096); - FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671); - FAIL_ON(drm_format_info_min_pitch(info, 1, 336) != 672); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) != - (uint64_t)UINT_MAX); - FAIL_ON(drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) != - (uint64_t)UINT_MAX + 1); - FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) != - (uint64_t)(UINT_MAX - 1)); - FAIL_ON(drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) != - (uint64_t)(UINT_MAX - 1)); - - /* Test 3 planes 8 bits per pixel format */ - info = drm_format_info(DRM_FORMAT_YUV422); - FAIL_ON(!info); - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 2, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 3, 0) != 0); - - FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1); - FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 1); - FAIL_ON(drm_format_info_min_pitch(info, 2, 1) != 1); - FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 1, 2) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 2, 2) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640); - FAIL_ON(drm_format_info_min_pitch(info, 1, 320) != 320); - FAIL_ON(drm_format_info_min_pitch(info, 2, 320) != 320); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024); - FAIL_ON(drm_format_info_min_pitch(info, 1, 512) != 512); - FAIL_ON(drm_format_info_min_pitch(info, 2, 512) != 512); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920); - FAIL_ON(drm_format_info_min_pitch(info, 1, 960) != 960); - FAIL_ON(drm_format_info_min_pitch(info, 2, 960) != 960); - FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096); - FAIL_ON(drm_format_info_min_pitch(info, 1, 2048) != 2048); - FAIL_ON(drm_format_info_min_pitch(info, 2, 2048) != 2048); - FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671); - FAIL_ON(drm_format_info_min_pitch(info, 1, 336) != 336); - FAIL_ON(drm_format_info_min_pitch(info, 2, 336) != 336); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) != - (uint64_t)UINT_MAX); - FAIL_ON(drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) != - (uint64_t)UINT_MAX / 2 + 1); - FAIL_ON(drm_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1) != - (uint64_t)UINT_MAX / 2 + 1); - FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2) != - (uint64_t)(UINT_MAX - 1) / 2); - FAIL_ON(drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) != - (uint64_t)(UINT_MAX - 1) / 2); - FAIL_ON(drm_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2) != - (uint64_t)(UINT_MAX - 1) / 2); - - /* Test tiled format */ - info = drm_format_info(DRM_FORMAT_X0L2); - FAIL_ON(!info); - FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0); - FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0); - - FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 4); - FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1280); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 2048); - FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 3840); - FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 8192); - FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 1342); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) != - (uint64_t)UINT_MAX * 2); - FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) != - (uint64_t)(UINT_MAX - 1) * 2); - - return 0; -} diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h index 42a10d7da51c..5709d967a5c4 100644 --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h +++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h @@ -17,9 +17,6 @@ #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n") int igt_check_plane_state(void *ignored); -int igt_check_drm_format_block_width(void *ignored); -int igt_check_drm_format_block_height(void *ignored); -int igt_check_drm_format_min_pitch(void *ignored); int igt_check_drm_framebuffer_create(void *ignored); int igt_dp_mst_calc_pbn_mode(void *ignored); int igt_dp_mst_sideband_msg_req_decode(void *ignored); diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index f2eced30a955..1aa1627cb5e6 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ - drm_cmdline_parser_test.o drm_rect_test.o + drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c new file mode 100644 index 000000000000..056cb8599d6d --- /dev/null +++ b/drivers/gpu/drm/tests/drm_format_test.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test cases for the drm_format functions + * + * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> + */ + +#include <kunit/test.h> + +#include <drm/drm_fourcc.h> + +static void igt_check_drm_format_block_width(struct kunit *test) +{ + const struct drm_format_info *info = NULL; + + /* Test invalid arguments */ + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1)); + + /* Test 1 plane format */ + info = drm_format_info(DRM_FORMAT_XRGB4444); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + + /* Test 2 planes format */ + info = drm_format_info(DRM_FORMAT_NV12); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0)); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 2)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + + /* Test 3 planes format */ + info = drm_format_info(DRM_FORMAT_YUV422); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0)); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 1)); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 2)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 3)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); + + /* Test a tiled format */ + info = drm_format_info(DRM_FORMAT_X0L0); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 2); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1)); +} + +static void igt_check_drm_format_block_height(struct kunit *test) +{ + const struct drm_format_info *info = NULL; + + /* Test invalid arguments */ + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1)); + + /* Test 1 plane format */ + info = drm_format_info(DRM_FORMAT_XRGB4444); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1)); + + /* Test 2 planes format */ + info = drm_format_info(DRM_FORMAT_NV12); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0)); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 2)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); + + /* Test 3 planes format */ + info = drm_format_info(DRM_FORMAT_YUV422); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0)); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 1)); + KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 2)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 3)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); + + /* Test a tiled format */ + info = drm_format_info(DRM_FORMAT_X0L0); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 2); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1)); + KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); +} + +static void igt_check_drm_format_min_pitch(struct kunit *test) +{ + const struct drm_format_info *info = NULL; + + /* Test invalid arguments */ + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + + /* Test 1 plane 8 bits per pixel format */ + info = drm_format_info(DRM_FORMAT_RGB332); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 640); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 1024); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 1920); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 4096); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 671); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), + (uint64_t)UINT_MAX); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), + (uint64_t)(UINT_MAX - 1)); + + /* Test 1 plane 16 bits per pixel format */ + info = drm_format_info(DRM_FORMAT_XRGB4444); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 4); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 1280); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 2048); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 3840); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 8192); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 1342); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), + (uint64_t)UINT_MAX * 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), + (uint64_t)(UINT_MAX - 1) * 2); + + /* Test 1 plane 24 bits per pixel format */ + info = drm_format_info(DRM_FORMAT_RGB888); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 3); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 6); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 1920); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 3072); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 5760); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 12288); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 2013); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), + (uint64_t)UINT_MAX * 3); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), + (uint64_t)(UINT_MAX - 1) * 3); + + /* Test 1 plane 32 bits per pixel format */ + info = drm_format_info(DRM_FORMAT_ABGR8888); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 4); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 8); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 2560); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 4096); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 7680); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 16384); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 2684); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), + (uint64_t)UINT_MAX * 4); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), + (uint64_t)(UINT_MAX - 1) * 4); + + /* Test 2 planes format */ + info = drm_format_info(DRM_FORMAT_NV12); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 2, 0)); + + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 640); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 320), 640); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 1024); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 512), 1024); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 1920); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 960), 1920); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 4096); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 2048), 4096); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 671); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 336), 672); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), + (uint64_t)UINT_MAX); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1), + (uint64_t)UINT_MAX + 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), + (uint64_t)(UINT_MAX - 1)); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2), + (uint64_t)(UINT_MAX - 1)); + + /* Test 3 planes 8 bits per pixel format */ + info = drm_format_info(DRM_FORMAT_YUV422); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 2, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 3, 0)); + + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 1), 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 2), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 2), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 640); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 320), 320); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 320), 320); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 1024); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 512), 512); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 512), 512); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 1920); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 960), 960); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 960), 960); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 4096); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 2048), 2048); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 2048), 2048); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 671); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 336), 336); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 336), 336); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), + (uint64_t)UINT_MAX); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1), + (uint64_t)UINT_MAX / 2 + 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1), + (uint64_t)UINT_MAX / 2 + 1); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2), + (uint64_t)(UINT_MAX - 1) / 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2), + (uint64_t)(UINT_MAX - 1) / 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2), + (uint64_t)(UINT_MAX - 1) / 2); + + /* Test tiled format */ + info = drm_format_info(DRM_FORMAT_X0L2); + KUNIT_EXPECT_TRUE(test, info); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0)); + KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0)); + + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 4); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 1280); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 2048); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 3840); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 8192); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 1342); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX), + (uint64_t)UINT_MAX * 2); + KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX - 1), + (uint64_t)(UINT_MAX - 1) * 2); +} + +static struct kunit_case drm_format_tests[] = { + KUNIT_CASE(igt_check_drm_format_block_width), + KUNIT_CASE(igt_check_drm_format_block_height), + KUNIT_CASE(igt_check_drm_format_min_pitch), + { } +}; + +static struct kunit_suite drm_format_test_suite = { + .name = "drm_format", + .test_cases = drm_format_tests, +}; + +kunit_test_suite(drm_format_test_suite); + +MODULE_LICENSE("GPL"); From 913b1e7ca77e0d04b74921e7328e3446f3a481be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:48 -0300 Subject: [PATCH 041/396] drm: selftest: convert drm_plane_helper selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM plane helper selftest to the KUnit API. Co-developed-by: Djakson C. G. Filho <djakson.filho@gmail.com> Signed-off-by: Djakson C. G. Filho <djakson.filho@gmail.com> Co-developed-by: Anderson Fraga <aaafraga@gmail.com> Signed-off-by: Anderson Fraga <aaafraga@gmail.com> Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-6-maira.canal@usp.br --- drivers/gpu/drm/selftests/Makefile | 4 +- .../gpu/drm/selftests/drm_modeset_selftests.h | 1 - .../drm/selftests/test-drm_modeset_common.h | 1 - drivers/gpu/drm/tests/Makefile | 2 +- .../drm_plane_helper_test.c} | 122 ++++++++++-------- 5 files changed, 71 insertions(+), 59 deletions(-) rename drivers/gpu/drm/{selftests/test-drm_plane_helper.c => tests/drm_plane_helper_test.c} (57%) diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index b7f252d886d0..9e0ccb482841 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \ - test-drm_framebuffer.o test-drm_dp_mst_helper.o +test-drm_modeset-y := test-drm_modeset_common.o test-drm_framebuffer.o \ + test-drm_dp_mst_helper.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \ test-drm_buddy.o diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h index 63061ef55eff..22e467f6465a 100644 --- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h +++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h @@ -6,7 +6,6 @@ * * Tests are executed in order by igt/drm_selftests_helper */ -selftest(check_plane_state, igt_check_plane_state) selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create) selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode) selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode) diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h index 5709d967a5c4..790f3cf31f0d 100644 --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h +++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h @@ -16,7 +16,6 @@ #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n") -int igt_check_plane_state(void *ignored); int igt_check_drm_framebuffer_create(void *ignored); int igt_dp_mst_calc_pbn_mode(void *ignored); int igt_dp_mst_sideband_msg_req_decode(void *ignored); diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 1aa1627cb5e6..4d44006a4f23 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ - drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o + drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o diff --git a/drivers/gpu/drm/selftests/test-drm_plane_helper.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c similarity index 57% rename from drivers/gpu/drm/selftests/test-drm_plane_helper.c rename to drivers/gpu/drm/tests/drm_plane_helper_test.c index 64e8938ab194..e298766cd41f 100644 --- a/drivers/gpu/drm/selftests/test-drm_plane_helper.c +++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-2.0 /* * Test cases for the drm_plane_helper functions + * + * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> */ -#define pr_fmt(fmt) "drm_plane_helper: " fmt +#include <kunit/test.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_plane_helper.h> #include <drm/drm_modes.h> -#include "test-drm_modeset_common.h" - static void set_src(struct drm_plane_state *plane_state, - unsigned src_x, unsigned src_y, - unsigned src_w, unsigned src_h) + unsigned int src_x, unsigned int src_y, + unsigned int src_w, unsigned int src_h) { plane_state->src_x = src_x; plane_state->src_y = src_y; @@ -23,8 +23,8 @@ static void set_src(struct drm_plane_state *plane_state, } static bool check_src_eq(struct drm_plane_state *plane_state, - unsigned src_x, unsigned src_y, - unsigned src_w, unsigned src_h) + unsigned int src_x, unsigned int src_y, + unsigned int src_w, unsigned int src_h) { if (plane_state->src.x1 < 0) { pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1); @@ -50,7 +50,7 @@ static bool check_src_eq(struct drm_plane_state *plane_state, static void set_crtc(struct drm_plane_state *plane_state, int crtc_x, int crtc_y, - unsigned crtc_w, unsigned crtc_h) + unsigned int crtc_w, unsigned int crtc_h) { plane_state->crtc_x = crtc_x; plane_state->crtc_y = crtc_y; @@ -60,7 +60,7 @@ static void set_crtc(struct drm_plane_state *plane_state, static bool check_crtc_eq(struct drm_plane_state *plane_state, int crtc_x, int crtc_y, - unsigned crtc_w, unsigned crtc_h) + unsigned int crtc_w, unsigned int crtc_h) { if (plane_state->dst.x1 != crtc_x || plane_state->dst.y1 != crtc_y || @@ -74,7 +74,7 @@ static bool check_crtc_eq(struct drm_plane_state *plane_state, return true; } -int igt_check_plane_state(void *ignored) +static void igt_check_plane_state(struct kunit *test) { int ret; @@ -83,9 +83,8 @@ int igt_check_plane_state(void *ignored) .enable = true, .active = true, .mode = { - DRM_MODE("1024x768", 0, 65000, 1024, 1048, - 1184, 1344, 0, 768, 771, 777, 806, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) + DRM_MODE("1024x768", 0, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, + 777, 806, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, }; static struct drm_plane plane = { @@ -109,10 +108,10 @@ int igt_check_plane_state(void *ignored) DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, false, false); - FAIL(ret < 0, "Simple clipping check should pass\n"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768)); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple clipping check should pass\n"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768)); /* Rotated clipping + reflection, no scaling. */ plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X; @@ -120,10 +119,10 @@ int igt_check_plane_state(void *ignored) DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, false, false); - FAIL(ret < 0, "Rotated clipping check should pass\n"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768)); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Rotated clipping check should pass\n"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768)); plane_state.rotation = DRM_MODE_ROTATE_0; /* Check whether positioning works correctly. */ @@ -133,16 +132,17 @@ int igt_check_plane_state(void *ignored) DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, false, false); - FAIL(!ret, "Should not be able to position on the crtc with can_position=false\n"); + KUNIT_EXPECT_TRUE_MSG(test, ret, + "Should not be able to position on the crtc with can_position=false\n"); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, true, false); - FAIL(ret < 0, "Simple positioning should work\n"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1023, 767)); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple positioning should work\n"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1023, 767)); /* Simple scaling tests. */ set_src(&plane_state, 0, 0, 512 << 16, 384 << 16); @@ -151,28 +151,28 @@ int igt_check_plane_state(void *ignored) 0x8001, DRM_PLANE_HELPER_NO_SCALING, false, false); - FAIL(!ret, "Upscaling out of range should fail.\n"); + KUNIT_EXPECT_TRUE_MSG(test, ret, "Upscaling out of range should fail.\n"); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, 0x8000, DRM_PLANE_HELPER_NO_SCALING, false, false); - FAIL(ret < 0, "Upscaling exactly 2x should work\n"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768)); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Upscaling exactly 2x should work\n"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768)); set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, DRM_PLANE_HELPER_NO_SCALING, 0x1ffff, false, false); - FAIL(!ret, "Downscaling out of range should fail.\n"); + KUNIT_EXPECT_TRUE_MSG(test, ret, "Downscaling out of range should fail.\n"); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, DRM_PLANE_HELPER_NO_SCALING, 0x20000, false, false); - FAIL(ret < 0, "Should succeed with exact scaling limit\n"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768)); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed with exact scaling limit\n"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768)); /* Testing rounding errors. */ set_src(&plane_state, 0, 0, 0x40001, 0x40001); @@ -181,10 +181,10 @@ int igt_check_plane_state(void *ignored) DRM_PLANE_HELPER_NO_SCALING, 0x10001, true, false); - FAIL(ret < 0, "Should succeed by clipping to exact multiple"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2)); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 1022, 766, 2, 2)); set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001); set_crtc(&plane_state, -2, -2, 1028, 772); @@ -192,10 +192,11 @@ int igt_check_plane_state(void *ignored) DRM_PLANE_HELPER_NO_SCALING, 0x10001, false, false); - FAIL(ret < 0, "Should succeed by clipping to exact multiple"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0x40002, 0x40002, 1024 << 16, 768 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768)); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0x40002, 0x40002, + 1024 << 16, 768 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768)); set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff); set_crtc(&plane_state, 1022, 766, 4, 4); @@ -203,11 +204,11 @@ int igt_check_plane_state(void *ignored) 0xffff, DRM_PLANE_HELPER_NO_SCALING, true, false); - FAIL(ret < 0, "Should succeed by clipping to exact multiple"); - FAIL_ON(!plane_state.visible); + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); /* Should not be rounded to 0x20001, which would be upscaling. */ - FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2)); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 1022, 766, 2, 2)); set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff); set_crtc(&plane_state, -2, -2, 1028, 772); @@ -215,10 +216,23 @@ int igt_check_plane_state(void *ignored) 0xffff, DRM_PLANE_HELPER_NO_SCALING, false, false); - FAIL(ret < 0, "Should succeed by clipping to exact multiple"); - FAIL_ON(!plane_state.visible); - FAIL_ON(!check_src_eq(&plane_state, 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16)); - FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768)); - - return 0; + KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); + KUNIT_EXPECT_TRUE(test, plane_state.visible); + KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0x3fffe, 0x3fffe, + 1024 << 16, 768 << 16)); + KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768)); } + +static struct kunit_case drm_plane_helper_test[] = { + KUNIT_CASE(igt_check_plane_state), + {} +}; + +static struct kunit_suite drm_plane_helper_test_suite = { + .name = "drm_plane_helper", + .test_cases = drm_plane_helper_test, +}; + +kunit_test_suite(drm_plane_helper_test_suite); + +MODULE_LICENSE("GPL"); From 848b3c0be2b944f633fe9beb28ad28f15c39f7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:49 -0300 Subject: [PATCH 042/396] drm: selftest: convert drm_dp_mst_helper selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM DP MST helper selftest to the KUnit API. Co-developed-by: Rubens Gomes Neto <rubens.gomes.neto@usp.br> Signed-off-by: Rubens Gomes Neto <rubens.gomes.neto@usp.br> Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-7-maira.canal@usp.br --- drivers/gpu/drm/selftests/Makefile | 3 +- .../gpu/drm/selftests/drm_modeset_selftests.h | 2 - .../drm/selftests/test-drm_modeset_common.h | 2 - drivers/gpu/drm/tests/Makefile | 3 +- .../drm_dp_mst_helper_test.c} | 89 +++++++++++-------- 5 files changed, 53 insertions(+), 46 deletions(-) rename drivers/gpu/drm/{selftests/test-drm_dp_mst_helper.c => tests/drm_dp_mst_helper_test.c} (72%) diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 9e0ccb482841..1539f55db9a7 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -test-drm_modeset-y := test-drm_modeset_common.o test-drm_framebuffer.o \ - test-drm_dp_mst_helper.o +test-drm_modeset-y := test-drm_modeset_common.o test-drm_framebuffer.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \ test-drm_buddy.o diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h index 22e467f6465a..40a29b8cf386 100644 --- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h +++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h @@ -7,5 +7,3 @@ * Tests are executed in order by igt/drm_selftests_helper */ selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create) -selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode) -selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode) diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h index 790f3cf31f0d..3feb2fea1a6b 100644 --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h +++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h @@ -17,7 +17,5 @@ #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n") int igt_check_drm_framebuffer_create(void *ignored); -int igt_dp_mst_calc_pbn_mode(void *ignored); -int igt_dp_mst_sideband_msg_req_decode(void *ignored); #endif diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 4d44006a4f23..5ffacd3eacf3 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ - drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o + drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \ + drm_dp_mst_helper_test.o diff --git a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c similarity index 72% rename from drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c rename to drivers/gpu/drm/tests/drm_dp_mst_helper_test.c index 4caa9be900ac..1d2fade56227 100644 --- a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c +++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c @@ -1,19 +1,22 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Test cases for the DRM DP MST helpers + * + * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> */ #define PREFIX_STR "[drm_dp_mst_helper]" +#include <kunit/test.h> + #include <linux/random.h> #include <drm/display/drm_dp_mst_helper.h> #include <drm/drm_print.h> #include "../display/drm_dp_mst_topology_internal.h" -#include "test-drm_modeset_common.h" -int igt_dp_mst_calc_pbn_mode(void *ignored) +static void igt_dp_mst_calc_pbn_mode(struct kunit *test) { int pbn, i; const struct { @@ -33,13 +36,11 @@ int igt_dp_mst_calc_pbn_mode(void *ignored) pbn = drm_dp_calc_pbn_mode(test_params[i].rate, test_params[i].bpp, test_params[i].dsc); - FAIL(pbn != test_params[i].expected, - "Expected PBN %d for clock %d bpp %d, got %d\n", + KUNIT_EXPECT_EQ_MSG(test, pbn, test_params[i].expected, + "Expected PBN %d for clock %d bpp %d, got %d\n", test_params[i].expected, test_params[i].rate, test_params[i].bpp, pbn); } - - return 0; } static bool @@ -176,66 +177,64 @@ out: return result; } -int igt_dp_mst_sideband_msg_req_decode(void *unused) +static void igt_dp_mst_sideband_msg_req_decode(struct kunit *test) { struct drm_dp_sideband_msg_req_body in = { 0 }; u8 data[] = { 0xff, 0x0, 0xdd }; int i; -#define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in)) - in.req_type = DP_ENUM_PATH_RESOURCES; in.u.port_num.port_number = 5; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_POWER_UP_PHY; in.u.port_num.port_number = 5; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_POWER_DOWN_PHY; in.u.port_num.port_number = 5; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_ALLOCATE_PAYLOAD; in.u.allocate_payload.number_sdp_streams = 3; for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++) in.u.allocate_payload.sdp_stream_sink[i] = i + 1; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.allocate_payload.port_number = 0xf; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.allocate_payload.vcpi = 0x7f; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.allocate_payload.pbn = U16_MAX; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_QUERY_PAYLOAD; in.u.query_payload.port_number = 0xf; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.query_payload.vcpi = 0x7f; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_REMOTE_DPCD_READ; in.u.dpcd_read.port_number = 0xf; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.dpcd_read.dpcd_address = 0xfedcb; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.dpcd_read.num_bytes = U8_MAX; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_REMOTE_DPCD_WRITE; in.u.dpcd_write.port_number = 0xf; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.dpcd_write.dpcd_address = 0xfedcb; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.dpcd_write.num_bytes = ARRAY_SIZE(data); in.u.dpcd_write.bytes = data; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_REMOTE_I2C_READ; in.u.i2c_read.port_number = 0xf; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.i2c_read.read_i2c_device_id = 0x7f; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.i2c_read.num_transactions = 3; in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3; for (i = 0; i < in.u.i2c_read.num_transactions; i++) { @@ -244,32 +243,44 @@ int igt_dp_mst_sideband_msg_req_decode(void *unused) in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i; in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i; } - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_REMOTE_I2C_WRITE; in.u.i2c_write.port_number = 0xf; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.i2c_write.write_i2c_device_id = 0x7f; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.i2c_write.num_bytes = ARRAY_SIZE(data); in.u.i2c_write.bytes = data; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.req_type = DP_QUERY_STREAM_ENC_STATUS; in.u.enc_status.stream_id = 1; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); get_random_bytes(in.u.enc_status.client_id, sizeof(in.u.enc_status.client_id)); - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.enc_status.stream_event = 3; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.enc_status.valid_stream_event = 0; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.enc_status.stream_behavior = 3; - DO_TEST(); + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); in.u.enc_status.valid_stream_behavior = 1; - DO_TEST(); - -#undef DO_TEST - return 0; + KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in)); } + +static struct kunit_case drm_dp_mst_helper_tests[] = { + KUNIT_CASE(igt_dp_mst_calc_pbn_mode), + KUNIT_CASE(igt_dp_mst_sideband_msg_req_decode), + { } +}; + +static struct kunit_suite drm_dp_mst_helper_test_suite = { + .name = "drm_dp_mst_helper", + .test_cases = drm_dp_mst_helper_tests, +}; + +kunit_test_suite(drm_dp_mst_helper_test_suite); + +MODULE_LICENSE("GPL"); From 9eb11f52a6285c0516046e11d45fa4be8714a1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:50 -0300 Subject: [PATCH 043/396] drm: selftest: convert drm_framebuffer selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM framebuffer selftest to the KUnit API. Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-8-maira.canal@usp.br --- drivers/gpu/drm/selftests/Makefile | 5 +- .../gpu/drm/selftests/drm_modeset_selftests.h | 9 --- .../drm/selftests/test-drm_modeset_common.c | 32 -------- .../drm/selftests/test-drm_modeset_common.h | 21 ----- drivers/gpu/drm/tests/Makefile | 2 +- .../drm_framebuffer_test.c} | 77 ++++++++++++------- 6 files changed, 53 insertions(+), 93 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/drm_modeset_selftests.h delete mode 100644 drivers/gpu/drm/selftests/test-drm_modeset_common.c delete mode 100644 drivers/gpu/drm/selftests/test-drm_modeset_common.h rename drivers/gpu/drm/{selftests/test-drm_framebuffer.c => tests/drm_framebuffer_test.c} (86%) diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 1539f55db9a7..f7db628b60cb 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1,5 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -test-drm_modeset-y := test-drm_modeset_common.o test-drm_framebuffer.o - -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \ - test-drm_buddy.o +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_buddy.o diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h deleted file mode 100644 index 40a29b8cf386..000000000000 --- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* List each unit test as selftest(name, function) - * - * The name is used as both an enum and expanded as igt__name to create - * a module parameter. It must be unique and legal for a C identifier. - * - * Tests are executed in order by igt/drm_selftests_helper - */ -selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create) diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.c b/drivers/gpu/drm/selftests/test-drm_modeset_common.c deleted file mode 100644 index 2a7f93774006..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.c +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Common file for modeset selftests. - */ - -#include <linux/module.h> - -#include "test-drm_modeset_common.h" - -#define TESTS "drm_modeset_selftests.h" -#include "drm_selftest.h" - -#include "drm_selftest.c" - -static int __init test_drm_modeset_init(void) -{ - int err; - - err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL); - - return err > 0 ? 0 : err; -} - -static void __exit test_drm_modeset_exit(void) -{ -} - -module_init(test_drm_modeset_init); -module_exit(test_drm_modeset_exit); - -MODULE_AUTHOR("Intel Corporation"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h deleted file mode 100644 index 3feb2fea1a6b..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef __TEST_DRM_MODESET_COMMON_H__ -#define __TEST_DRM_MODESET_COMMON_H__ - -#include <linux/errno.h> -#include <linux/printk.h> - -#define FAIL(test, msg, ...) \ - do { \ - if (test) { \ - pr_err("%s/%u: " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - return -EINVAL; \ - } \ - } while (0) - -#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n") - -int igt_check_drm_framebuffer_create(void *ignored); - -#endif diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 5ffacd3eacf3..4cbfd9098d56 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \ - drm_dp_mst_helper_test.o + drm_dp_mst_helper_test.o drm_framebuffer_test.o diff --git a/drivers/gpu/drm/selftests/test-drm_framebuffer.c b/drivers/gpu/drm/tests/drm_framebuffer_test.c similarity index 86% rename from drivers/gpu/drm/selftests/test-drm_framebuffer.c rename to drivers/gpu/drm/tests/drm_framebuffer_test.c index f6d66285c5fc..ec7a08ba4056 100644 --- a/drivers/gpu/drm/selftests/test-drm_framebuffer.c +++ b/drivers/gpu/drm/tests/drm_framebuffer_test.c @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* * Test cases for the drm_framebuffer functions + * + * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> */ -#include <linux/kernel.h> +#include <kunit/test.h> #include <drm/drm_device.h> #include <drm/drm_mode.h> @@ -12,8 +14,6 @@ #include "../drm_crtc_internal.h" -#include "test-drm_modeset_common.h" - #define MIN_WIDTH 4 #define MAX_WIDTH 4096 #define MIN_HEIGHT 4 @@ -73,12 +73,14 @@ static struct drm_framebuffer_test createbuffer_tests[] = { }, { .buffer_created = 0, .name = "ABGR8888 Out of bound height * pitch combination", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, - .handles = { 1, 0, 0 }, .offsets = { UINT_MAX - 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, + .handles = { 1, 0, 0 }, .offsets = { UINT_MAX - 1, 0, 0 }, + .pitches = { 4 * MAX_WIDTH, 0, 0 }, } }, { .buffer_created = 1, .name = "ABGR8888 Large buffer offset", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, - .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, + .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, + .pitches = { 4 * MAX_WIDTH, 0, 0 }, } }, { .buffer_created = 1, .name = "ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers", @@ -89,11 +91,13 @@ static struct drm_framebuffer_test createbuffer_tests[] = { }, { .buffer_created = 1, .name = "ABGR8888 Valid buffer modifier", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, - .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, - .flags = DRM_MODE_FB_MODIFIERS, .modifier = { AFBC_FORMAT_MOD_YTR, 0, 0 }, + .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, + .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS, + .modifier = { AFBC_FORMAT_MOD_YTR, 0, 0 }, } }, -{ .buffer_created = 0, .name = "ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)", +{ .buffer_created = 0, + .name = "ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS, @@ -143,7 +147,8 @@ static struct drm_framebuffer_test createbuffer_tests[] = { { .buffer_created = 1, .name = "NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS, - .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 }, + .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, + DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, } }, @@ -164,7 +169,8 @@ static struct drm_framebuffer_test createbuffer_tests[] = { }, { .buffer_created = 0, .name = "NV12 Handle for inexistent plane", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, - .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, + .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, + .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, } }, { .buffer_created = 1, .name = "NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS", @@ -203,24 +209,29 @@ static struct drm_framebuffer_test createbuffer_tests[] = { }, { .buffer_created = 1, .name = "YVU420 Different buffer offsets/pitches", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, - .handles = { 1, 1, 1 }, .offsets = { MAX_WIDTH, MAX_WIDTH + MAX_WIDTH * MAX_HEIGHT, - MAX_WIDTH + 2 * MAX_WIDTH * MAX_HEIGHT }, - .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1, DIV_ROUND_UP(MAX_WIDTH, 2) + 7 }, + .handles = { 1, 1, 1 }, .offsets = { MAX_WIDTH, MAX_WIDTH + + MAX_WIDTH * MAX_HEIGHT, MAX_WIDTH + 2 * MAX_WIDTH * MAX_HEIGHT }, + .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1, + DIV_ROUND_UP(MAX_WIDTH, 2) + 7 }, } }, -{ .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS", +{ .buffer_created = 0, + .name = "YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, } }, -{ .buffer_created = 0, .name = "YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS", +{ .buffer_created = 0, + .name = "YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, - .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 }, + .handles = { 1, 1, 1 }, + .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, } }, -{ .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS", +{ .buffer_created = 0, + .name = "YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 }, @@ -230,7 +241,8 @@ static struct drm_framebuffer_test createbuffer_tests[] = { { .buffer_created = 1, .name = "YVU420 Valid modifier", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, - .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE }, + .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, + AFBC_FORMAT_MOD_SPARSE }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, } }, @@ -245,8 +257,8 @@ static struct drm_framebuffer_test createbuffer_tests[] = { { .buffer_created = 0, .name = "YVU420 Modifier for inexistent plane", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, - .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, - AFBC_FORMAT_MOD_SPARSE }, + .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, + AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, } }, @@ -276,7 +288,8 @@ static struct drm_framebuffer_test createbuffer_tests[] = { .pitches = { 2 * MAX_WIDTH + 1, 0, 0 } } }, -{ .buffer_created = 1, .name = "X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set", +{ .buffer_created = 1, + .name = "X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set", .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, .handles = { 1, 0, 0 }, .offsets = { 0, 0, 3 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 } @@ -336,15 +349,27 @@ static int execute_drm_mode_fb_cmd2(struct drm_mode_fb_cmd2 *r) return buffer_created; } -int igt_check_drm_framebuffer_create(void *ignored) +static void igt_check_drm_framebuffer_create(struct kunit *test) { int i = 0; for (i = 0; i < ARRAY_SIZE(createbuffer_tests); i++) { - FAIL(createbuffer_tests[i].buffer_created != - execute_drm_mode_fb_cmd2(&createbuffer_tests[i].cmd), + KUNIT_EXPECT_EQ_MSG(test, createbuffer_tests[i].buffer_created, + execute_drm_mode_fb_cmd2(&createbuffer_tests[i].cmd), "Test %d: \"%s\" failed\n", i, createbuffer_tests[i].name); } - - return 0; } + +static struct kunit_case drm_framebuffer_tests[] = { + KUNIT_CASE(igt_check_drm_framebuffer_create), + { } +}; + +static struct kunit_suite drm_framebuffer_test_suite = { + .name = "drm_framebuffer", + .test_cases = drm_framebuffer_tests, +}; + +kunit_test_suite(drm_framebuffer_test_suite); + +MODULE_LICENSE("GPL"); From 932da861956ac425ba4e65f7696458f96d833883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <maira.canal@usp.br> Date: Fri, 8 Jul 2022 17:30:51 -0300 Subject: [PATCH 044/396] drm: selftest: convert drm_buddy selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM buddy selftest to the KUnit API. Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-9-maira.canal@usp.br --- drivers/gpu/drm/selftests/Makefile | 2 +- .../gpu/drm/selftests/drm_buddy_selftests.h | 15 - drivers/gpu/drm/selftests/test-drm_buddy.c | 994 ------------------ drivers/gpu/drm/tests/Makefile | 2 +- drivers/gpu/drm/tests/drm_buddy_test.c | 756 +++++++++++++ 5 files changed, 758 insertions(+), 1011 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h delete mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c create mode 100644 drivers/gpu/drm/tests/drm_buddy_test.c diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index f7db628b60cb..a4ebecb8146b 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1,2 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_buddy.o +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h deleted file mode 100644 index 455b756c4ae5..000000000000 --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* List each unit test as selftest(name, function) - * - * The name is used as both an enum and expanded as igt__name to create - * a module parameter. It must be unique and legal for a C identifier. - * - * Tests are executed in order by igt/drm_buddy - */ -selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ -selftest(buddy_alloc_limit, igt_buddy_alloc_limit) -selftest(buddy_alloc_range, igt_buddy_alloc_range) -selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic) -selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic) -selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke) -selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological) diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c deleted file mode 100644 index aca0c491040f..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_buddy.c +++ /dev/null @@ -1,994 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2019 Intel Corporation - */ - -#define pr_fmt(fmt) "drm_buddy: " fmt - -#include <linux/module.h> -#include <linux/prime_numbers.h> -#include <linux/sched/signal.h> - -#include <drm/drm_buddy.h> - -#include "../lib/drm_random.h" - -#define TESTS "drm_buddy_selftests.h" -#include "drm_selftest.h" - -#define IGT_TIMEOUT(name__) \ - unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT - -static unsigned int random_seed; - -static inline u64 get_size(int order, u64 chunk_size) -{ - return (1 << order) * chunk_size; -} - -__printf(2, 3) -static bool __igt_timeout(unsigned long timeout, const char *fmt, ...) -{ - va_list va; - - if (!signal_pending(current)) { - cond_resched(); - if (time_before(jiffies, timeout)) - return false; - } - - if (fmt) { - va_start(va, fmt); - vprintk(fmt, va); - va_end(va); - } - - return true; -} - -static inline const char *yesno(bool v) -{ - return v ? "yes" : "no"; -} - -static void __igt_dump_block(struct drm_buddy *mm, - struct drm_buddy_block *block, - bool buddy) -{ - pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n", - block->header, - drm_buddy_block_state(block), - drm_buddy_block_order(block), - drm_buddy_block_offset(block), - drm_buddy_block_size(mm, block), - yesno(!block->parent), - yesno(buddy)); -} - -static void igt_dump_block(struct drm_buddy *mm, - struct drm_buddy_block *block) -{ - struct drm_buddy_block *buddy; - - __igt_dump_block(mm, block, false); - - buddy = drm_get_buddy(block); - if (buddy) - __igt_dump_block(mm, buddy, true); -} - -static int igt_check_block(struct drm_buddy *mm, - struct drm_buddy_block *block) -{ - struct drm_buddy_block *buddy; - unsigned int block_state; - u64 block_size; - u64 offset; - int err = 0; - - block_state = drm_buddy_block_state(block); - - if (block_state != DRM_BUDDY_ALLOCATED && - block_state != DRM_BUDDY_FREE && - block_state != DRM_BUDDY_SPLIT) { - pr_err("block state mismatch\n"); - err = -EINVAL; - } - - block_size = drm_buddy_block_size(mm, block); - offset = drm_buddy_block_offset(block); - - if (block_size < mm->chunk_size) { - pr_err("block size smaller than min size\n"); - err = -EINVAL; - } - - if (!is_power_of_2(block_size)) { - pr_err("block size not power of two\n"); - err = -EINVAL; - } - - if (!IS_ALIGNED(block_size, mm->chunk_size)) { - pr_err("block size not aligned to min size\n"); - err = -EINVAL; - } - - if (!IS_ALIGNED(offset, mm->chunk_size)) { - pr_err("block offset not aligned to min size\n"); - err = -EINVAL; - } - - if (!IS_ALIGNED(offset, block_size)) { - pr_err("block offset not aligned to block size\n"); - err = -EINVAL; - } - - buddy = drm_get_buddy(block); - - if (!buddy && block->parent) { - pr_err("buddy has gone fishing\n"); - err = -EINVAL; - } - - if (buddy) { - if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) { - pr_err("buddy has wrong offset\n"); - err = -EINVAL; - } - - if (drm_buddy_block_size(mm, buddy) != block_size) { - pr_err("buddy size mismatch\n"); - err = -EINVAL; - } - - if (drm_buddy_block_state(buddy) == block_state && - block_state == DRM_BUDDY_FREE) { - pr_err("block and its buddy are free\n"); - err = -EINVAL; - } - } - - return err; -} - -static int igt_check_blocks(struct drm_buddy *mm, - struct list_head *blocks, - u64 expected_size, - bool is_contiguous) -{ - struct drm_buddy_block *block; - struct drm_buddy_block *prev; - u64 total; - int err = 0; - - block = NULL; - prev = NULL; - total = 0; - - list_for_each_entry(block, blocks, link) { - err = igt_check_block(mm, block); - - if (!drm_buddy_block_is_allocated(block)) { - pr_err("block not allocated\n"), - err = -EINVAL; - } - - if (is_contiguous && prev) { - u64 prev_block_size; - u64 prev_offset; - u64 offset; - - prev_offset = drm_buddy_block_offset(prev); - prev_block_size = drm_buddy_block_size(mm, prev); - offset = drm_buddy_block_offset(block); - - if (offset != (prev_offset + prev_block_size)) { - pr_err("block offset mismatch\n"); - err = -EINVAL; - } - } - - if (err) - break; - - total += drm_buddy_block_size(mm, block); - prev = block; - } - - if (!err) { - if (total != expected_size) { - pr_err("size mismatch, expected=%llx, found=%llx\n", - expected_size, total); - err = -EINVAL; - } - return err; - } - - if (prev) { - pr_err("prev block, dump:\n"); - igt_dump_block(mm, prev); - } - - pr_err("bad block, dump:\n"); - igt_dump_block(mm, block); - - return err; -} - -static int igt_check_mm(struct drm_buddy *mm) -{ - struct drm_buddy_block *root; - struct drm_buddy_block *prev; - unsigned int i; - u64 total; - int err = 0; - - if (!mm->n_roots) { - pr_err("n_roots is zero\n"); - return -EINVAL; - } - - if (mm->n_roots != hweight64(mm->size)) { - pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n", - mm->n_roots, hweight64(mm->size)); - return -EINVAL; - } - - root = NULL; - prev = NULL; - total = 0; - - for (i = 0; i < mm->n_roots; ++i) { - struct drm_buddy_block *block; - unsigned int order; - - root = mm->roots[i]; - if (!root) { - pr_err("root(%u) is NULL\n", i); - err = -EINVAL; - break; - } - - err = igt_check_block(mm, root); - - if (!drm_buddy_block_is_free(root)) { - pr_err("root not free\n"); - err = -EINVAL; - } - - order = drm_buddy_block_order(root); - - if (!i) { - if (order != mm->max_order) { - pr_err("max order root missing\n"); - err = -EINVAL; - } - } - - if (prev) { - u64 prev_block_size; - u64 prev_offset; - u64 offset; - - prev_offset = drm_buddy_block_offset(prev); - prev_block_size = drm_buddy_block_size(mm, prev); - offset = drm_buddy_block_offset(root); - - if (offset != (prev_offset + prev_block_size)) { - pr_err("root offset mismatch\n"); - err = -EINVAL; - } - } - - block = list_first_entry_or_null(&mm->free_list[order], - struct drm_buddy_block, - link); - if (block != root) { - pr_err("root mismatch at order=%u\n", order); - err = -EINVAL; - } - - if (err) - break; - - prev = root; - total += drm_buddy_block_size(mm, root); - } - - if (!err) { - if (total != mm->size) { - pr_err("expected mm size=%llx, found=%llx\n", mm->size, - total); - err = -EINVAL; - } - return err; - } - - if (prev) { - pr_err("prev root(%u), dump:\n", i - 1); - igt_dump_block(mm, prev); - } - - if (root) { - pr_err("bad root(%u), dump:\n", i); - igt_dump_block(mm, root); - } - - return err; -} - -static void igt_mm_config(u64 *size, u64 *chunk_size) -{ - DRM_RND_STATE(prng, random_seed); - u32 s, ms; - - /* Nothing fancy, just try to get an interesting bit pattern */ - - prandom_seed_state(&prng, random_seed); - - /* Let size be a random number of pages up to 8 GB (2M pages) */ - s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng); - /* Let the chunk size be a random power of 2 less than size */ - ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng)); - /* Round size down to the chunk size */ - s &= -ms; - - /* Convert from pages to bytes */ - *chunk_size = (u64)ms << 12; - *size = (u64)s << 12; -} - -static int igt_buddy_alloc_pathological(void *arg) -{ - u64 mm_size, size, min_page_size, start = 0; - struct drm_buddy_block *block; - const int max_order = 3; - unsigned long flags = 0; - int order, top, err; - struct drm_buddy mm; - LIST_HEAD(blocks); - LIST_HEAD(holes); - LIST_HEAD(tmp); - - /* - * Create a pot-sized mm, then allocate one of each possible - * order within. This should leave the mm with exactly one - * page left. Free the largest block, then whittle down again. - * Eventually we will have a fully 50% fragmented mm. - */ - - mm_size = PAGE_SIZE << max_order; - err = drm_buddy_init(&mm, mm_size, PAGE_SIZE); - if (err) { - pr_err("buddy_init failed(%d)\n", err); - return err; - } - BUG_ON(mm.max_order != max_order); - - for (top = max_order; top; top--) { - /* Make room by freeing the largest allocated block */ - block = list_first_entry_or_null(&blocks, typeof(*block), link); - if (block) { - list_del(&block->link); - drm_buddy_free_block(&mm, block); - } - - for (order = top; order--; ) { - size = min_page_size = get_size(order, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, - min_page_size, &tmp, flags); - if (err) { - pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n", - order, top); - goto err; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - } - - /* There should be one final page for this sub-allocation */ - size = min_page_size = get_size(0, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (err) { - pr_info("buddy_alloc hit -ENOMEM for hole\n"); - goto err; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &holes); - - size = min_page_size = get_size(top, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (!err) { - pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!", - top, max_order); - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - err = -EINVAL; - goto err; - } - } - - drm_buddy_free_list(&mm, &holes); - - /* Nothing larger than blocks of chunk_size now available */ - for (order = 1; order <= max_order; order++) { - size = min_page_size = get_size(order, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (!err) { - pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!", - order); - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - err = -EINVAL; - goto err; - } - } - - if (err) - err = 0; - -err: - list_splice_tail(&holes, &blocks); - drm_buddy_free_list(&mm, &blocks); - drm_buddy_fini(&mm); - return err; -} - -static int igt_buddy_alloc_smoke(void *arg) -{ - u64 mm_size, min_page_size, chunk_size, start = 0; - unsigned long flags = 0; - struct drm_buddy mm; - int *order; - int err, i; - - DRM_RND_STATE(prng, random_seed); - IGT_TIMEOUT(end_time); - - igt_mm_config(&mm_size, &chunk_size); - - err = drm_buddy_init(&mm, mm_size, chunk_size); - if (err) { - pr_err("buddy_init failed(%d)\n", err); - return err; - } - - order = drm_random_order(mm.max_order + 1, &prng); - if (!order) { - err = -ENOMEM; - goto out_fini; - } - - for (i = 0; i <= mm.max_order; ++i) { - struct drm_buddy_block *block; - int max_order = order[i]; - bool timeout = false; - LIST_HEAD(blocks); - u64 total, size; - LIST_HEAD(tmp); - int order; - - err = igt_check_mm(&mm); - if (err) { - pr_err("pre-mm check failed, abort\n"); - break; - } - - order = max_order; - total = 0; - - do { -retry: - size = min_page_size = get_size(order, chunk_size); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, - min_page_size, &tmp, flags); - if (err) { - if (err == -ENOMEM) { - pr_info("buddy_alloc hit -ENOMEM with order=%d\n", - order); - } else { - if (order--) { - err = 0; - goto retry; - } - - pr_err("buddy_alloc with order=%d failed(%d)\n", - order, err); - } - - break; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - break; - } - - list_move_tail(&block->link, &blocks); - - if (drm_buddy_block_order(block) != order) { - pr_err("buddy_alloc order mismatch\n"); - err = -EINVAL; - break; - } - - total += drm_buddy_block_size(&mm, block); - - if (__igt_timeout(end_time, NULL)) { - timeout = true; - break; - } - } while (total < mm.size); - - if (!err) - err = igt_check_blocks(&mm, &blocks, total, false); - - drm_buddy_free_list(&mm, &blocks); - - if (!err) { - err = igt_check_mm(&mm); - if (err) - pr_err("post-mm check failed\n"); - } - - if (err || timeout) - break; - - cond_resched(); - } - - if (err == -ENOMEM) - err = 0; - - kfree(order); -out_fini: - drm_buddy_fini(&mm); - - return err; -} - -static int igt_buddy_alloc_pessimistic(void *arg) -{ - u64 mm_size, size, min_page_size, start = 0; - struct drm_buddy_block *block, *bn; - const unsigned int max_order = 16; - unsigned long flags = 0; - struct drm_buddy mm; - unsigned int order; - LIST_HEAD(blocks); - LIST_HEAD(tmp); - int err; - - /* - * Create a pot-sized mm, then allocate one of each possible - * order within. This should leave the mm with exactly one - * page left. - */ - - mm_size = PAGE_SIZE << max_order; - err = drm_buddy_init(&mm, mm_size, PAGE_SIZE); - if (err) { - pr_err("buddy_init failed(%d)\n", err); - return err; - } - BUG_ON(mm.max_order != max_order); - - for (order = 0; order < max_order; order++) { - size = min_page_size = get_size(order, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (err) { - pr_info("buddy_alloc hit -ENOMEM with order=%d\n", - order); - goto err; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - } - - /* And now the last remaining block available */ - size = min_page_size = get_size(0, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (err) { - pr_info("buddy_alloc hit -ENOMEM on final alloc\n"); - goto err; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - - /* Should be completely full! */ - for (order = max_order; order--; ) { - size = min_page_size = get_size(order, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (!err) { - pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!", - order); - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - err = -EINVAL; - goto err; - } - } - - block = list_last_entry(&blocks, typeof(*block), link); - list_del(&block->link); - drm_buddy_free_block(&mm, block); - - /* As we free in increasing size, we make available larger blocks */ - order = 1; - list_for_each_entry_safe(block, bn, &blocks, link) { - list_del(&block->link); - drm_buddy_free_block(&mm, block); - - size = min_page_size = get_size(order, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (err) { - pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n", - order); - goto err; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_del(&block->link); - drm_buddy_free_block(&mm, block); - order++; - } - - /* To confirm, now the whole mm should be available */ - size = min_page_size = get_size(max_order, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (err) { - pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n", - max_order); - goto err; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_del(&block->link); - drm_buddy_free_block(&mm, block); - -err: - drm_buddy_free_list(&mm, &blocks); - drm_buddy_fini(&mm); - return err; -} - -static int igt_buddy_alloc_optimistic(void *arg) -{ - u64 mm_size, size, min_page_size, start = 0; - struct drm_buddy_block *block; - unsigned long flags = 0; - const int max_order = 16; - struct drm_buddy mm; - LIST_HEAD(blocks); - LIST_HEAD(tmp); - int order, err; - - /* - * Create a mm with one block of each order available, and - * try to allocate them all. - */ - - mm_size = PAGE_SIZE * ((1 << (max_order + 1)) - 1); - err = drm_buddy_init(&mm, - mm_size, - PAGE_SIZE); - if (err) { - pr_err("buddy_init failed(%d)\n", err); - return err; - } - - BUG_ON(mm.max_order != max_order); - - for (order = 0; order <= max_order; order++) { - size = min_page_size = get_size(order, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (err) { - pr_info("buddy_alloc hit -ENOMEM with order=%d\n", - order); - goto err; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - } - - /* Should be completely full! */ - size = min_page_size = get_size(0, PAGE_SIZE); - err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags); - if (!err) { - pr_info("buddy_alloc unexpectedly succeeded, it should be full!"); - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_blocks has no blocks\n"); - err = -EINVAL; - goto err; - } - - list_move_tail(&block->link, &blocks); - err = -EINVAL; - goto err; - } else { - err = 0; - } - -err: - drm_buddy_free_list(&mm, &blocks); - drm_buddy_fini(&mm); - return err; -} - -static int igt_buddy_alloc_range(void *arg) -{ - unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION; - u64 offset, size, rem, chunk_size, end; - unsigned long page_num; - struct drm_buddy mm; - LIST_HEAD(blocks); - int err; - - igt_mm_config(&size, &chunk_size); - - err = drm_buddy_init(&mm, size, chunk_size); - if (err) { - pr_err("buddy_init failed(%d)\n", err); - return err; - } - - err = igt_check_mm(&mm); - if (err) { - pr_err("pre-mm check failed, abort, abort, abort!\n"); - goto err_fini; - } - - rem = mm.size; - offset = 0; - - for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) { - struct drm_buddy_block *block; - LIST_HEAD(tmp); - - size = min(page_num * mm.chunk_size, rem); - end = offset + size; - - err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags); - if (err) { - if (err == -ENOMEM) { - pr_info("alloc_range hit -ENOMEM with size=%llx\n", - size); - } else { - pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n", - offset, size, err); - } - - break; - } - - block = list_first_entry_or_null(&tmp, - struct drm_buddy_block, - link); - if (!block) { - pr_err("alloc_range has no blocks\n"); - err = -EINVAL; - break; - } - - if (drm_buddy_block_offset(block) != offset) { - pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n", - drm_buddy_block_offset(block), offset); - err = -EINVAL; - } - - if (!err) - err = igt_check_blocks(&mm, &tmp, size, true); - - list_splice_tail(&tmp, &blocks); - - if (err) - break; - - offset += size; - - rem -= size; - if (!rem) - break; - - cond_resched(); - } - - if (err == -ENOMEM) - err = 0; - - drm_buddy_free_list(&mm, &blocks); - - if (!err) { - err = igt_check_mm(&mm); - if (err) - pr_err("post-mm check failed\n"); - } - -err_fini: - drm_buddy_fini(&mm); - - return err; -} - -static int igt_buddy_alloc_limit(void *arg) -{ - u64 size = U64_MAX, start = 0; - struct drm_buddy_block *block; - unsigned long flags = 0; - LIST_HEAD(allocated); - struct drm_buddy mm; - int err; - - err = drm_buddy_init(&mm, size, PAGE_SIZE); - if (err) - return err; - - if (mm.max_order != DRM_BUDDY_MAX_ORDER) { - pr_err("mm.max_order(%d) != %d\n", - mm.max_order, DRM_BUDDY_MAX_ORDER); - err = -EINVAL; - goto out_fini; - } - - size = mm.chunk_size << mm.max_order; - err = drm_buddy_alloc_blocks(&mm, start, size, size, - PAGE_SIZE, &allocated, flags); - - if (unlikely(err)) - goto out_free; - - block = list_first_entry_or_null(&allocated, - struct drm_buddy_block, - link); - - if (!block) { - err = -EINVAL; - goto out_fini; - } - - if (drm_buddy_block_order(block) != mm.max_order) { - pr_err("block order(%d) != %d\n", - drm_buddy_block_order(block), mm.max_order); - err = -EINVAL; - goto out_free; - } - - if (drm_buddy_block_size(&mm, block) != - BIT_ULL(mm.max_order) * PAGE_SIZE) { - pr_err("block size(%llu) != %llu\n", - drm_buddy_block_size(&mm, block), - BIT_ULL(mm.max_order) * PAGE_SIZE); - err = -EINVAL; - goto out_free; - } - -out_free: - drm_buddy_free_list(&mm, &allocated); -out_fini: - drm_buddy_fini(&mm); - return err; -} - -static int igt_sanitycheck(void *ignored) -{ - pr_info("%s - ok!\n", __func__); - return 0; -} - -#include "drm_selftest.c" - -static int __init test_drm_buddy_init(void) -{ - int err; - - while (!random_seed) - random_seed = get_random_int(); - - pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n", - random_seed); - err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL); - - return err > 0 ? 0 : err; -} - -static void __exit test_drm_buddy_exit(void) -{ -} - -module_init(test_drm_buddy_init); -module_exit(test_drm_buddy_exit); - -MODULE_AUTHOR("Intel Corporation"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 4cbfd9098d56..cff59189598f 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \ - drm_dp_mst_helper_test.o drm_framebuffer_test.o + drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c new file mode 100644 index 000000000000..d76f83833e75 --- /dev/null +++ b/drivers/gpu/drm/tests/drm_buddy_test.c @@ -0,0 +1,756 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2019 Intel Corporation + * Copyright © 2022 Maíra Canal <mairacanal@riseup.net> + */ + +#include <kunit/test.h> + +#include <linux/prime_numbers.h> +#include <linux/sched/signal.h> + +#include <drm/drm_buddy.h> + +#include "../lib/drm_random.h" + +#define IGT_TIMEOUT(name__) \ + unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT + +static unsigned int random_seed; + +static inline u64 get_size(int order, u64 chunk_size) +{ + return (1 << order) * chunk_size; +} + +__printf(2, 3) +static bool __igt_timeout(unsigned long timeout, const char *fmt, ...) +{ + va_list va; + + if (!signal_pending(current)) { + cond_resched(); + if (time_before(jiffies, timeout)) + return false; + } + + if (fmt) { + va_start(va, fmt); + vprintk(fmt, va); + va_end(va); + } + + return true; +} + +static void __igt_dump_block(struct kunit *test, struct drm_buddy *mm, + struct drm_buddy_block *block, bool buddy) +{ + kunit_err(test, "block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%d buddy=%d\n", + block->header, drm_buddy_block_state(block), + drm_buddy_block_order(block), drm_buddy_block_offset(block), + drm_buddy_block_size(mm, block), !block->parent, buddy); +} + +static void igt_dump_block(struct kunit *test, struct drm_buddy *mm, + struct drm_buddy_block *block) +{ + struct drm_buddy_block *buddy; + + __igt_dump_block(test, mm, block, false); + + buddy = drm_get_buddy(block); + if (buddy) + __igt_dump_block(test, mm, buddy, true); +} + +static int igt_check_block(struct kunit *test, struct drm_buddy *mm, + struct drm_buddy_block *block) +{ + struct drm_buddy_block *buddy; + unsigned int block_state; + u64 block_size; + u64 offset; + int err = 0; + + block_state = drm_buddy_block_state(block); + + if (block_state != DRM_BUDDY_ALLOCATED && + block_state != DRM_BUDDY_FREE && block_state != DRM_BUDDY_SPLIT) { + kunit_err(test, "block state mismatch\n"); + err = -EINVAL; + } + + block_size = drm_buddy_block_size(mm, block); + offset = drm_buddy_block_offset(block); + + if (block_size < mm->chunk_size) { + kunit_err(test, "block size smaller than min size\n"); + err = -EINVAL; + } + + if (!is_power_of_2(block_size)) { + kunit_err(test, "block size not power of two\n"); + err = -EINVAL; + } + + if (!IS_ALIGNED(block_size, mm->chunk_size)) { + kunit_err(test, "block size not aligned to min size\n"); + err = -EINVAL; + } + + if (!IS_ALIGNED(offset, mm->chunk_size)) { + kunit_err(test, "block offset not aligned to min size\n"); + err = -EINVAL; + } + + if (!IS_ALIGNED(offset, block_size)) { + kunit_err(test, "block offset not aligned to block size\n"); + err = -EINVAL; + } + + buddy = drm_get_buddy(block); + + if (!buddy && block->parent) { + kunit_err(test, "buddy has gone fishing\n"); + err = -EINVAL; + } + + if (buddy) { + if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) { + kunit_err(test, "buddy has wrong offset\n"); + err = -EINVAL; + } + + if (drm_buddy_block_size(mm, buddy) != block_size) { + kunit_err(test, "buddy size mismatch\n"); + err = -EINVAL; + } + + if (drm_buddy_block_state(buddy) == block_state && + block_state == DRM_BUDDY_FREE) { + kunit_err(test, "block and its buddy are free\n"); + err = -EINVAL; + } + } + + return err; +} + +static int igt_check_blocks(struct kunit *test, struct drm_buddy *mm, + struct list_head *blocks, u64 expected_size, bool is_contiguous) +{ + struct drm_buddy_block *block; + struct drm_buddy_block *prev; + u64 total; + int err = 0; + + block = NULL; + prev = NULL; + total = 0; + + list_for_each_entry(block, blocks, link) { + err = igt_check_block(test, mm, block); + + if (!drm_buddy_block_is_allocated(block)) { + kunit_err(test, "block not allocated\n"); + err = -EINVAL; + } + + if (is_contiguous && prev) { + u64 prev_block_size; + u64 prev_offset; + u64 offset; + + prev_offset = drm_buddy_block_offset(prev); + prev_block_size = drm_buddy_block_size(mm, prev); + offset = drm_buddy_block_offset(block); + + if (offset != (prev_offset + prev_block_size)) { + kunit_err(test, "block offset mismatch\n"); + err = -EINVAL; + } + } + + if (err) + break; + + total += drm_buddy_block_size(mm, block); + prev = block; + } + + if (!err) { + if (total != expected_size) { + kunit_err(test, "size mismatch, expected=%llx, found=%llx\n", + expected_size, total); + err = -EINVAL; + } + return err; + } + + if (prev) { + kunit_err(test, "prev block, dump:\n"); + igt_dump_block(test, mm, prev); + } + + kunit_err(test, "bad block, dump:\n"); + igt_dump_block(test, mm, block); + + return err; +} + +static int igt_check_mm(struct kunit *test, struct drm_buddy *mm) +{ + struct drm_buddy_block *root; + struct drm_buddy_block *prev; + unsigned int i; + u64 total; + int err = 0; + + if (!mm->n_roots) { + kunit_err(test, "n_roots is zero\n"); + return -EINVAL; + } + + if (mm->n_roots != hweight64(mm->size)) { + kunit_err(test, "n_roots mismatch, n_roots=%u, expected=%lu\n", + mm->n_roots, hweight64(mm->size)); + return -EINVAL; + } + + root = NULL; + prev = NULL; + total = 0; + + for (i = 0; i < mm->n_roots; ++i) { + struct drm_buddy_block *block; + unsigned int order; + + root = mm->roots[i]; + if (!root) { + kunit_err(test, "root(%u) is NULL\n", i); + err = -EINVAL; + break; + } + + err = igt_check_block(test, mm, root); + + if (!drm_buddy_block_is_free(root)) { + kunit_err(test, "root not free\n"); + err = -EINVAL; + } + + order = drm_buddy_block_order(root); + + if (!i) { + if (order != mm->max_order) { + kunit_err(test, "max order root missing\n"); + err = -EINVAL; + } + } + + if (prev) { + u64 prev_block_size; + u64 prev_offset; + u64 offset; + + prev_offset = drm_buddy_block_offset(prev); + prev_block_size = drm_buddy_block_size(mm, prev); + offset = drm_buddy_block_offset(root); + + if (offset != (prev_offset + prev_block_size)) { + kunit_err(test, "root offset mismatch\n"); + err = -EINVAL; + } + } + + block = list_first_entry_or_null(&mm->free_list[order], + struct drm_buddy_block, link); + if (block != root) { + kunit_err(test, "root mismatch at order=%u\n", order); + err = -EINVAL; + } + + if (err) + break; + + prev = root; + total += drm_buddy_block_size(mm, root); + } + + if (!err) { + if (total != mm->size) { + kunit_err(test, "expected mm size=%llx, found=%llx\n", + mm->size, total); + err = -EINVAL; + } + return err; + } + + if (prev) { + kunit_err(test, "prev root(%u), dump:\n", i - 1); + igt_dump_block(test, mm, prev); + } + + if (root) { + kunit_err(test, "bad root(%u), dump:\n", i); + igt_dump_block(test, mm, root); + } + + return err; +} + +static void igt_mm_config(u64 *size, u64 *chunk_size) +{ + DRM_RND_STATE(prng, random_seed); + u32 s, ms; + + /* Nothing fancy, just try to get an interesting bit pattern */ + + prandom_seed_state(&prng, random_seed); + + /* Let size be a random number of pages up to 8 GB (2M pages) */ + s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng); + /* Let the chunk size be a random power of 2 less than size */ + ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng)); + /* Round size down to the chunk size */ + s &= -ms; + + /* Convert from pages to bytes */ + *chunk_size = (u64)ms << 12; + *size = (u64)s << 12; +} + +static void igt_buddy_alloc_pathological(struct kunit *test) +{ + u64 mm_size, size, start = 0; + struct drm_buddy_block *block; + const int max_order = 3; + unsigned long flags = 0; + int order, top; + struct drm_buddy mm; + LIST_HEAD(blocks); + LIST_HEAD(holes); + LIST_HEAD(tmp); + + /* + * Create a pot-sized mm, then allocate one of each possible + * order within. This should leave the mm with exactly one + * page left. Free the largest block, then whittle down again. + * Eventually we will have a fully 50% fragmented mm. + */ + + mm_size = PAGE_SIZE << max_order; + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, PAGE_SIZE), + "buddy_init failed\n"); + + KUNIT_EXPECT_EQ(test, mm.max_order, max_order); + + for (top = max_order; top; top--) { + /* Make room by freeing the largest allocated block */ + block = list_first_entry_or_null(&blocks, typeof(*block), link); + if (block) { + list_del(&block->link); + drm_buddy_free_block(&mm, block); + } + + for (order = top; order--;) { + size = get_size(order, PAGE_SIZE); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, + mm_size, size, size, + &tmp, flags), + "buddy_alloc hit -ENOMEM with order=%d, top=%d\n", + order, top); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_move_tail(&block->link, &blocks); + } + + /* There should be one final page for this sub-allocation */ + size = get_size(0, PAGE_SIZE); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc hit -ENOMEM for hole\n"); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_move_tail(&block->link, &holes); + + size = get_size(top, PAGE_SIZE); + KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!", + top, max_order); + } + + drm_buddy_free_list(&mm, &holes); + + /* Nothing larger than blocks of chunk_size now available */ + for (order = 1; order <= max_order; order++) { + size = get_size(order, PAGE_SIZE); + KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc unexpectedly succeeded at order %d, it should be full!", + order); + } + + list_splice_tail(&holes, &blocks); + drm_buddy_free_list(&mm, &blocks); + drm_buddy_fini(&mm); +} + +static void igt_buddy_alloc_smoke(struct kunit *test) +{ + u64 mm_size, chunk_size, start = 0; + unsigned long flags = 0; + struct drm_buddy mm; + int *order; + int i; + + DRM_RND_STATE(prng, random_seed); + IGT_TIMEOUT(end_time); + + igt_mm_config(&mm_size, &chunk_size); + + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, chunk_size), + "buddy_init failed\n"); + + order = drm_random_order(mm.max_order + 1, &prng); + KUNIT_ASSERT_TRUE(test, order); + + for (i = 0; i <= mm.max_order; ++i) { + struct drm_buddy_block *block; + int max_order = order[i]; + bool timeout = false; + LIST_HEAD(blocks); + u64 total, size; + LIST_HEAD(tmp); + int order, err; + + KUNIT_ASSERT_FALSE_MSG(test, igt_check_mm(test, &mm), + "pre-mm check failed, abort\n"); + + order = max_order; + total = 0; + + do { +retry: + size = get_size(order, chunk_size); + err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags); + if (err) { + if (err == -ENOMEM) { + KUNIT_FAIL(test, "buddy_alloc hit -ENOMEM with order=%d\n", + order); + } else { + if (order--) { + err = 0; + goto retry; + } + + KUNIT_FAIL(test, "buddy_alloc with order=%d failed\n", + order); + } + + break; + } + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_move_tail(&block->link, &blocks); + KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_order(block), order, + "buddy_alloc order mismatch\n"); + + total += drm_buddy_block_size(&mm, block); + + if (__igt_timeout(end_time, NULL)) { + timeout = true; + break; + } + } while (total < mm.size); + + if (!err) + err = igt_check_blocks(test, &mm, &blocks, total, false); + + drm_buddy_free_list(&mm, &blocks); + + if (!err) { + KUNIT_EXPECT_FALSE_MSG(test, igt_check_mm(test, &mm), + "post-mm check failed\n"); + } + + if (err || timeout) + break; + + cond_resched(); + } + + kfree(order); + drm_buddy_fini(&mm); +} + +static void igt_buddy_alloc_pessimistic(struct kunit *test) +{ + u64 mm_size, size, start = 0; + struct drm_buddy_block *block, *bn; + const unsigned int max_order = 16; + unsigned long flags = 0; + struct drm_buddy mm; + unsigned int order; + LIST_HEAD(blocks); + LIST_HEAD(tmp); + + /* + * Create a pot-sized mm, then allocate one of each possible + * order within. This should leave the mm with exactly one + * page left. + */ + + mm_size = PAGE_SIZE << max_order; + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, PAGE_SIZE), + "buddy_init failed\n"); + + KUNIT_EXPECT_EQ(test, mm.max_order, max_order); + + for (order = 0; order < max_order; order++) { + size = get_size(order, PAGE_SIZE); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc hit -ENOMEM with order=%d\n", + order); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_move_tail(&block->link, &blocks); + } + + /* And now the last remaining block available */ + size = get_size(0, PAGE_SIZE); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc hit -ENOMEM on final alloc\n"); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_move_tail(&block->link, &blocks); + + /* Should be completely full! */ + for (order = max_order; order--;) { + size = get_size(order, PAGE_SIZE); + KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc unexpectedly succeeded, it should be full!"); + } + + block = list_last_entry(&blocks, typeof(*block), link); + list_del(&block->link); + drm_buddy_free_block(&mm, block); + + /* As we free in increasing size, we make available larger blocks */ + order = 1; + list_for_each_entry_safe(block, bn, &blocks, link) { + list_del(&block->link); + drm_buddy_free_block(&mm, block); + + size = get_size(order, PAGE_SIZE); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc hit -ENOMEM with order=%d\n", + order); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_del(&block->link); + drm_buddy_free_block(&mm, block); + order++; + } + + /* To confirm, now the whole mm should be available */ + size = get_size(max_order, PAGE_SIZE); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc (realloc) hit -ENOMEM with order=%d\n", + max_order); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_del(&block->link); + drm_buddy_free_block(&mm, block); + drm_buddy_free_list(&mm, &blocks); + drm_buddy_fini(&mm); +} + +static void igt_buddy_alloc_optimistic(struct kunit *test) +{ + u64 mm_size, size, start = 0; + struct drm_buddy_block *block; + unsigned long flags = 0; + const int max_order = 16; + struct drm_buddy mm; + LIST_HEAD(blocks); + LIST_HEAD(tmp); + int order; + + /* + * Create a mm with one block of each order available, and + * try to allocate them all. + */ + + mm_size = PAGE_SIZE * ((1 << (max_order + 1)) - 1); + + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, PAGE_SIZE), + "buddy_init failed\n"); + + KUNIT_EXPECT_EQ(test, mm.max_order, max_order); + + for (order = 0; order <= max_order; order++) { + size = get_size(order, PAGE_SIZE); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc hit -ENOMEM with order=%d\n", + order); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); + + list_move_tail(&block->link, &blocks); + } + + /* Should be completely full! */ + size = get_size(0, PAGE_SIZE); + KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + size, size, &tmp, flags), + "buddy_alloc unexpectedly succeeded, it should be full!"); + + drm_buddy_free_list(&mm, &blocks); + drm_buddy_fini(&mm); +} + +static void igt_buddy_alloc_range(struct kunit *test) +{ + unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION; + u64 offset, size, rem, chunk_size, end; + unsigned long page_num; + struct drm_buddy mm; + LIST_HEAD(blocks); + + igt_mm_config(&size, &chunk_size); + + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, size, chunk_size), + "buddy_init failed"); + + KUNIT_ASSERT_FALSE_MSG(test, igt_check_mm(test, &mm), + "pre-mm check failed, abort!"); + + rem = mm.size; + offset = 0; + + for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) { + struct drm_buddy_block *block; + LIST_HEAD(tmp); + + size = min(page_num * mm.chunk_size, rem); + end = offset + size; + + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, offset, end, + size, mm.chunk_size, + &tmp, flags), + "alloc_range with offset=%llx, size=%llx failed\n", offset, size); + + block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_range has no blocks\n"); + + KUNIT_ASSERT_EQ_MSG(test, drm_buddy_block_offset(block), offset, + "alloc_range start offset mismatch, found=%llx, expected=%llx\n", + drm_buddy_block_offset(block), offset); + + KUNIT_ASSERT_FALSE(test, igt_check_blocks(test, &mm, &tmp, size, true)); + + list_splice_tail(&tmp, &blocks); + + offset += size; + + rem -= size; + if (!rem) + break; + + cond_resched(); + } + + drm_buddy_free_list(&mm, &blocks); + + KUNIT_EXPECT_FALSE_MSG(test, igt_check_mm(test, &mm), "post-mm check failed\n"); + + drm_buddy_fini(&mm); +} + +static void igt_buddy_alloc_limit(struct kunit *test) +{ + u64 size = U64_MAX, start = 0; + struct drm_buddy_block *block; + unsigned long flags = 0; + LIST_HEAD(allocated); + struct drm_buddy mm; + + KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, size, PAGE_SIZE)); + + KUNIT_EXPECT_EQ_MSG(test, mm.max_order, DRM_BUDDY_MAX_ORDER, + "mm.max_order(%d) != %d\n", mm.max_order, + DRM_BUDDY_MAX_ORDER); + + size = mm.chunk_size << mm.max_order; + KUNIT_EXPECT_FALSE(test, drm_buddy_alloc_blocks(&mm, start, size, size, + PAGE_SIZE, &allocated, flags)); + + block = list_first_entry_or_null(&allocated, struct drm_buddy_block, link); + KUNIT_EXPECT_TRUE(test, block); + + KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_order(block), mm.max_order, + "block order(%d) != %d\n", + drm_buddy_block_order(block), mm.max_order); + + KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_size(&mm, block), + BIT_ULL(mm.max_order) * PAGE_SIZE, + "block size(%llu) != %llu\n", + drm_buddy_block_size(&mm, block), + BIT_ULL(mm.max_order) * PAGE_SIZE); + + drm_buddy_free_list(&mm, &allocated); + drm_buddy_fini(&mm); +} + +static int drm_buddy_init_test(struct kunit *test) +{ + while (!random_seed) + random_seed = get_random_int(); + + return 0; +} + +static struct kunit_case drm_buddy_tests[] = { + KUNIT_CASE(igt_buddy_alloc_limit), + KUNIT_CASE(igt_buddy_alloc_range), + KUNIT_CASE(igt_buddy_alloc_optimistic), + KUNIT_CASE(igt_buddy_alloc_pessimistic), + KUNIT_CASE(igt_buddy_alloc_smoke), + KUNIT_CASE(igt_buddy_alloc_pathological), + {} +}; + +static struct kunit_suite drm_buddy_test_suite = { + .name = "drm_buddy", + .init = drm_buddy_init_test, + .test_cases = drm_buddy_tests, +}; + +kunit_test_suite(drm_buddy_test_suite); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL"); From fc8d29e298cf47e07c2764ec1c340c1df8e50431 Mon Sep 17 00:00:00 2001 From: Arthur Grillo <arthur.grillo@usp.br> Date: Fri, 8 Jul 2022 17:30:52 -0300 Subject: [PATCH 045/396] drm: selftest: convert drm_mm selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM mm selftest to the KUnit API. Signed-off-by: Arthur Grillo <arthur.grillo@usp.br> Tested-by: David Gow <davidgow@google.com> Acked-by: Daniel Latypov <dlatypov@google.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Maíra Canal <maira.canal@usp.br> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-10-maira.canal@usp.br --- Documentation/gpu/todo.rst | 11 - drivers/gpu/drm/Kconfig | 20 - drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/selftests/Makefile | 2 - drivers/gpu/drm/selftests/drm_mm_selftests.h | 28 - drivers/gpu/drm/selftests/drm_selftest.c | 109 -- drivers/gpu/drm/selftests/drm_selftest.h | 41 - drivers/gpu/drm/tests/Makefile | 2 +- .../test-drm_mm.c => tests/drm_mm_test.c} | 1248 +++++++---------- 9 files changed, 509 insertions(+), 953 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/Makefile delete mode 100644 drivers/gpu/drm/selftests/drm_mm_selftests.h delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.c delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.h rename drivers/gpu/drm/{selftests/test-drm_mm.c => tests/drm_mm_test.c} (55%) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 513b20ccef1e..10bfb50908d1 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -617,17 +617,6 @@ Contact: Javier Martinez Canillas <javierm@redhat.com> Level: Intermediate -Convert Kernel Selftests (kselftest) to KUnit tests when appropriate --------------------------------------------------------------------- - -Many of the `Kselftest <https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html>`_ -tests in DRM could be converted to Kunit tests instead, since that framework -is more suitable for unit testing. - -Contact: Javier Martinez Canillas <javierm@redhat.com> - -Level: Starter - Enable trinity for DRM ---------------------- diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 06822ecf51c6..1c91e1e861a5 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -50,26 +50,6 @@ config DRM_DEBUG_MM If in doubt, say "N". -config DRM_DEBUG_SELFTEST - tristate "kselftests for DRM" - depends on DRM - depends on DEBUG_KERNEL - select PRIME_NUMBERS - select DRM_DISPLAY_DP_HELPER - select DRM_DISPLAY_HELPER - select DRM_LIB_RANDOM - select DRM_KMS_HELPER - select DRM_BUDDY - select DRM_EXPORT_FOR_TESTS if m - default n - help - This option provides kernel modules that can be used to run - various selftests on parts of the DRM api. This option is not - useful for distributions or general kernels, but only for kernel - developers working on DRM and associated drivers. - - If in doubt, say "N". - config DRM_KUNIT_TEST tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS depends on DRM && KUNIT diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index e7af358e6dda..25016dcab55e 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -75,7 +75,6 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o # Drivers and the rest # -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/ obj-$(CONFIG_DRM_KUNIT_TEST) += tests/ obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile deleted file mode 100644 index a4ebecb8146b..000000000000 --- a/drivers/gpu/drm/selftests/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h deleted file mode 100644 index 8c87c964176b..000000000000 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* List each unit test as selftest(name, function) - * - * The name is used as both an enum and expanded as igt__name to create - * a module parameter. It must be unique and legal for a C identifier. - * - * Tests are executed in order by igt/drm_mm - */ -selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ -selftest(init, igt_init) -selftest(debug, igt_debug) -selftest(reserve, igt_reserve) -selftest(insert, igt_insert) -selftest(replace, igt_replace) -selftest(insert_range, igt_insert_range) -selftest(align, igt_align) -selftest(frag, igt_frag) -selftest(align32, igt_align32) -selftest(align64, igt_align64) -selftest(evict, igt_evict) -selftest(evict_range, igt_evict_range) -selftest(bottomup, igt_bottomup) -selftest(lowest, igt_lowest) -selftest(topdown, igt_topdown) -selftest(highest, igt_highest) -selftest(color, igt_color) -selftest(color_evict, igt_color_evict) -selftest(color_evict_range, igt_color_evict_range) diff --git a/drivers/gpu/drm/selftests/drm_selftest.c b/drivers/gpu/drm/selftests/drm_selftest.c deleted file mode 100644 index e29ed9faef5b..000000000000 --- a/drivers/gpu/drm/selftests/drm_selftest.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright © 2016 Intel Corporation - * - * 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. - */ - -#include <linux/compiler.h> - -#define selftest(name, func) __idx_##name, -enum { -#include TESTS -}; -#undef selftest - -#define selftest(n, f) [__idx_##n] = { .name = #n, .func = f }, -static struct drm_selftest { - bool enabled; - const char *name; - int (*func)(void *); -} selftests[] = { -#include TESTS -}; -#undef selftest - -/* Embed the line number into the parameter name so that we can order tests */ -#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), n)) -#define selftest_0(n, func, id) \ -module_param_named(id, selftests[__idx_##n].enabled, bool, 0400); -#define selftest(n, func) selftest_0(n, func, param(n)) -#include TESTS -#undef selftest - -static void set_default_test_all(struct drm_selftest *st, unsigned long count) -{ - unsigned long i; - - for (i = 0; i < count; i++) - if (st[i].enabled) - return; - - for (i = 0; i < count; i++) - st[i].enabled = true; -} - -static int run_selftests(struct drm_selftest *st, - unsigned long count, - void *data) -{ - int err = 0; - - set_default_test_all(st, count); - - /* Tests are listed in natural order in drm_*_selftests.h */ - for (; count--; st++) { - if (!st->enabled) - continue; - - pr_debug("drm: Running %s\n", st->name); - err = st->func(data); - if (err) - break; - } - - if (WARN(err > 0 || err == -ENOTTY, - "%s returned %d, conflicting with selftest's magic values!\n", - st->name, err)) - err = -1; - - rcu_barrier(); - return err; -} - -static int __maybe_unused -__drm_subtests(const char *caller, - const struct drm_subtest *st, - int count, - void *data) -{ - int err; - - for (; count--; st++) { - pr_debug("Running %s/%s\n", caller, st->name); - err = st->func(data); - if (err) { - pr_err("%s: %s failed with error %d\n", - caller, st->name, err); - return err; - } - } - - return 0; -} diff --git a/drivers/gpu/drm/selftests/drm_selftest.h b/drivers/gpu/drm/selftests/drm_selftest.h deleted file mode 100644 index c784ec02ff53..000000000000 --- a/drivers/gpu/drm/selftests/drm_selftest.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2016 Intel Corporation - * - * 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. - */ - -#ifndef __DRM_SELFTEST_H__ -#define __DRM_SELFTEST_H__ - -struct drm_subtest { - int (*func)(void *data); - const char *name; -}; - -static int __drm_subtests(const char *caller, - const struct drm_subtest *st, - int count, - void *data); -#define drm_subtests(T, data) \ - __drm_subtests(__func__, T, ARRAY_SIZE(T), data) - -#define SUBTEST(x) { x, #x } - -#endif /* __DRM_SELFTEST_H__ */ diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index cff59189598f..91b70f7d2769 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \ - drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o + drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o drm_mm_test.o diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/tests/drm_mm_test.c similarity index 55% rename from drivers/gpu/drm/selftests/test-drm_mm.c rename to drivers/gpu/drm/tests/drm_mm_test.c index b768b53c4aee..1e2c1aa524bd 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/tests/drm_mm_test.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Test cases for the drm_mm range manager + * + * Copyright (c) 2022 Arthur Grillo <arthur.grillo@usp.br> */ -#define pr_fmt(fmt) "drm_mm: " fmt +#include <kunit/test.h> -#include <linux/module.h> #include <linux/prime_numbers.h> #include <linux/slab.h> #include <linux/random.h> @@ -16,9 +17,6 @@ #include "../lib/drm_random.h" -#define TESTS "drm_mm_selftests.h" -#include "drm_selftest.h" - static unsigned int random_seed; static unsigned int max_iterations = 8192; static unsigned int max_prime = 128; @@ -45,13 +43,7 @@ static const struct insert_mode { {} }; -static int igt_sanitycheck(void *ignored) -{ - pr_info("%s - ok!\n", __func__); - return 0; -} - -static bool assert_no_holes(const struct drm_mm *mm) +static bool assert_no_holes(struct kunit *test, const struct drm_mm *mm) { struct drm_mm_node *hole; u64 hole_start, __always_unused hole_end; @@ -61,13 +53,14 @@ static bool assert_no_holes(const struct drm_mm *mm) drm_mm_for_each_hole(hole, mm, hole_start, hole_end) count++; if (count) { - pr_err("Expected to find no holes (after reserve), found %lu instead\n", count); + KUNIT_FAIL(test, + "Expected to find no holes (after reserve), found %lu instead\n", count); return false; } drm_mm_for_each_node(hole, mm) { if (drm_mm_hole_follows(hole)) { - pr_err("Hole follows node, expected none!\n"); + KUNIT_FAIL(test, "Hole follows node, expected none!\n"); return false; } } @@ -75,7 +68,7 @@ static bool assert_no_holes(const struct drm_mm *mm) return true; } -static bool assert_one_hole(const struct drm_mm *mm, u64 start, u64 end) +static bool assert_one_hole(struct kunit *test, const struct drm_mm *mm, u64 start, u64 end) { struct drm_mm_node *hole; u64 hole_start, hole_end; @@ -89,62 +82,62 @@ static bool assert_one_hole(const struct drm_mm *mm, u64 start, u64 end) drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { if (start != hole_start || end != hole_end) { if (ok) - pr_err("empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n", - hole_start, hole_end, - start, end); + KUNIT_FAIL(test, + "empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n", + hole_start, hole_end, start, end); ok = false; } count++; } if (count != 1) { - pr_err("Expected to find one hole, found %lu instead\n", count); + KUNIT_FAIL(test, "Expected to find one hole, found %lu instead\n", count); ok = false; } return ok; } -static bool assert_continuous(const struct drm_mm *mm, u64 size) +static bool assert_continuous(struct kunit *test, const struct drm_mm *mm, u64 size) { struct drm_mm_node *node, *check, *found; unsigned long n; u64 addr; - if (!assert_no_holes(mm)) + if (!assert_no_holes(test, mm)) return false; n = 0; addr = 0; drm_mm_for_each_node(node, mm) { if (node->start != addr) { - pr_err("node[%ld] list out of order, expected %llx found %llx\n", - n, addr, node->start); + KUNIT_FAIL(test, "node[%ld] list out of order, expected %llx found %llx\n", + n, addr, node->start); return false; } if (node->size != size) { - pr_err("node[%ld].size incorrect, expected %llx, found %llx\n", - n, size, node->size); + KUNIT_FAIL(test, "node[%ld].size incorrect, expected %llx, found %llx\n", + n, size, node->size); return false; } if (drm_mm_hole_follows(node)) { - pr_err("node[%ld] is followed by a hole!\n", n); + KUNIT_FAIL(test, "node[%ld] is followed by a hole!\n", n); return false; } found = NULL; drm_mm_for_each_node_in_range(check, mm, addr, addr + size) { if (node != check) { - pr_err("lookup return wrong node, expected start %llx, found %llx\n", - node->start, check->start); + KUNIT_FAIL(test, + "lookup return wrong node, expected start %llx, found %llx\n", + node->start, check->start); return false; } found = check; } if (!found) { - pr_err("lookup failed for node %llx + %llx\n", - addr, size); + KUNIT_FAIL(test, "lookup failed for node %llx + %llx\n", addr, size); return false; } @@ -166,107 +159,96 @@ static u64 misalignment(struct drm_mm_node *node, u64 alignment) return rem; } -static bool assert_node(struct drm_mm_node *node, struct drm_mm *mm, +static bool assert_node(struct kunit *test, struct drm_mm_node *node, struct drm_mm *mm, u64 size, u64 alignment, unsigned long color) { bool ok = true; if (!drm_mm_node_allocated(node) || node->mm != mm) { - pr_err("node not allocated\n"); + KUNIT_FAIL(test, "node not allocated\n"); ok = false; } if (node->size != size) { - pr_err("node has wrong size, found %llu, expected %llu\n", - node->size, size); + KUNIT_FAIL(test, "node has wrong size, found %llu, expected %llu\n", + node->size, size); ok = false; } if (misalignment(node, alignment)) { - pr_err("node is misaligned, start %llx rem %llu, expected alignment %llu\n", - node->start, misalignment(node, alignment), alignment); + KUNIT_FAIL(test, + "node is misaligned, start %llx rem %llu, expected alignment %llu\n", + node->start, misalignment(node, alignment), alignment); ok = false; } if (node->color != color) { - pr_err("node has wrong color, found %lu, expected %lu\n", - node->color, color); + KUNIT_FAIL(test, "node has wrong color, found %lu, expected %lu\n", + node->color, color); ok = false; } return ok; } -#define show_mm(mm) do { \ - struct drm_printer __p = drm_debug_printer(__func__); \ - drm_mm_print((mm), &__p); } while (0) - -static int igt_init(void *ignored) +static void igt_mm_init(struct kunit *test) { const unsigned int size = 4096; struct drm_mm mm; struct drm_mm_node tmp; - int ret = -EINVAL; /* Start with some simple checks on initialising the struct drm_mm */ memset(&mm, 0, sizeof(mm)); - if (drm_mm_initialized(&mm)) { - pr_err("zeroed mm claims to be initialized\n"); - return ret; - } + KUNIT_ASSERT_FALSE_MSG(test, drm_mm_initialized(&mm), + "zeroed mm claims to be initialized\n"); memset(&mm, 0xff, sizeof(mm)); drm_mm_init(&mm, 0, size); if (!drm_mm_initialized(&mm)) { - pr_err("mm claims not to be initialized\n"); + KUNIT_FAIL(test, "mm claims not to be initialized\n"); goto out; } if (!drm_mm_clean(&mm)) { - pr_err("mm not empty on creation\n"); + KUNIT_FAIL(test, "mm not empty on creation\n"); goto out; } /* After creation, it should all be one massive hole */ - if (!assert_one_hole(&mm, 0, size)) { - ret = -EINVAL; + if (!assert_one_hole(test, &mm, 0, size)) { + KUNIT_FAIL(test, ""); goto out; } memset(&tmp, 0, sizeof(tmp)); tmp.start = 0; tmp.size = size; - ret = drm_mm_reserve_node(&mm, &tmp); - if (ret) { - pr_err("failed to reserve whole drm_mm\n"); + if (drm_mm_reserve_node(&mm, &tmp)) { + KUNIT_FAIL(test, "failed to reserve whole drm_mm\n"); goto out; } /* After filling the range entirely, there should be no holes */ - if (!assert_no_holes(&mm)) { - ret = -EINVAL; + if (!assert_no_holes(test, &mm)) { + KUNIT_FAIL(test, ""); goto out; } /* And then after emptying it again, the massive hole should be back */ drm_mm_remove_node(&tmp); - if (!assert_one_hole(&mm, 0, size)) { - ret = -EINVAL; + if (!assert_one_hole(test, &mm, 0, size)) { + KUNIT_FAIL(test, ""); goto out; } out: - if (ret) - show_mm(&mm); drm_mm_takedown(&mm); - return ret; } -static int igt_debug(void *ignored) +static void igt_mm_debug(struct kunit *test) { struct drm_mm mm; struct drm_mm_node nodes[2]; - int ret; /* Create a small drm_mm with a couple of nodes and a few holes, and * check that the debug iterator doesn't explode over a trivial drm_mm. @@ -277,24 +259,15 @@ static int igt_debug(void *ignored) memset(nodes, 0, sizeof(nodes)); nodes[0].start = 512; nodes[0].size = 1024; - ret = drm_mm_reserve_node(&mm, &nodes[0]); - if (ret) { - pr_err("failed to reserve node[0] {start=%lld, size=%lld)\n", - nodes[0].start, nodes[0].size); - return ret; - } + KUNIT_ASSERT_FALSE_MSG(test, drm_mm_reserve_node(&mm, &nodes[0]), + "failed to reserve node[0] {start=%lld, size=%lld)\n", + nodes[0].start, nodes[0].size); nodes[1].size = 1024; nodes[1].start = 4096 - 512 - nodes[1].size; - ret = drm_mm_reserve_node(&mm, &nodes[1]); - if (ret) { - pr_err("failed to reserve node[1] {start=%lld, size=%lld)\n", - nodes[1].start, nodes[1].size); - return ret; - } - - show_mm(&mm); - return 0; + KUNIT_ASSERT_FALSE_MSG(test, drm_mm_reserve_node(&mm, &nodes[1]), + "failed to reserve node[0] {start=%lld, size=%lld)\n", + nodes[0].start, nodes[0].size); } static struct drm_mm_node *set_node(struct drm_mm_node *node, @@ -305,7 +278,7 @@ static struct drm_mm_node *set_node(struct drm_mm_node *node, return node; } -static bool expect_reserve_fail(struct drm_mm *mm, struct drm_mm_node *node) +static bool expect_reserve_fail(struct kunit *test, struct drm_mm *mm, struct drm_mm_node *node) { int err; @@ -314,17 +287,18 @@ static bool expect_reserve_fail(struct drm_mm *mm, struct drm_mm_node *node) return true; if (!err) { - pr_err("impossible reserve succeeded, node %llu + %llu\n", - node->start, node->size); + KUNIT_FAIL(test, "impossible reserve succeeded, node %llu + %llu\n", + node->start, node->size); drm_mm_remove_node(node); } else { - pr_err("impossible reserve failed with wrong error %d [expected %d], node %llu + %llu\n", + KUNIT_FAIL(test, + "impossible reserve failed with wrong error %d [expected %d], node %llu + %llu\n", err, -ENOSPC, node->start, node->size); } return false; } -static bool check_reserve_boundaries(struct drm_mm *mm, +static bool check_reserve_boundaries(struct kunit *test, struct drm_mm *mm, unsigned int count, u64 size) { @@ -339,29 +313,27 @@ static bool check_reserve_boundaries(struct drm_mm *mm, B(size * count, 0), B(-size, size), B(-size, -size), - B(-size, 2*size), + B(-size, 2 * size), B(0, -size), B(size, -size), - B(count*size, size), - B(count*size, -size), - B(count*size, count*size), - B(count*size, -count*size), - B(count*size, -(count+1)*size), - B((count+1)*size, size), - B((count+1)*size, -size), - B((count+1)*size, -2*size), + B(count * size, size), + B(count * size, -size), + B(count * size, count * size), + B(count * size, -count * size), + B(count * size, -(count + 1) * size), + B((count + 1) * size, size), + B((count + 1) * size, -size), + B((count + 1) * size, -2 * size), #undef B }; struct drm_mm_node tmp = {}; int n; for (n = 0; n < ARRAY_SIZE(boundaries); n++) { - if (!expect_reserve_fail(mm, - set_node(&tmp, - boundaries[n].start, - boundaries[n].size))) { - pr_err("boundary[%d:%s] failed, count=%u, size=%lld\n", - n, boundaries[n].name, count, size); + if (!expect_reserve_fail(test, mm, set_node(&tmp, boundaries[n].start, + boundaries[n].size))) { + KUNIT_FAIL(test, "boundary[%d:%s] failed, count=%u, size=%lld\n", + n, boundaries[n].name, count, size); return false; } } @@ -369,7 +341,7 @@ static bool check_reserve_boundaries(struct drm_mm *mm, return true; } -static int __igt_reserve(unsigned int count, u64 size) +static int __igt_reserve(struct kunit *test, unsigned int count, u64 size) { DRM_RND_STATE(prng, random_seed); struct drm_mm mm; @@ -377,7 +349,7 @@ static int __igt_reserve(unsigned int count, u64 size) unsigned int *order, n, m, o = 0; int ret, err; - /* For exercising drm_mm_reserve_node(), we want to check that + /* For exercising drm_mm_reserve_node(struct kunit *test, ), we want to check that * reservations outside of the drm_mm range are rejected, and to * overlapping and otherwise already occupied ranges. Afterwards, * the tree and nodes should be intact. @@ -392,13 +364,12 @@ static int __igt_reserve(unsigned int count, u64 size) goto err; nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err_order; + KUNIT_ASSERT_TRUE(test, nodes); ret = -EINVAL; drm_mm_init(&mm, 0, count * size); - if (!check_reserve_boundaries(&mm, count, size)) + if (!check_reserve_boundaries(test, &mm, count, size)) goto out; for (n = 0; n < count; n++) { @@ -407,57 +378,53 @@ static int __igt_reserve(unsigned int count, u64 size) err = drm_mm_reserve_node(&mm, &nodes[n]); if (err) { - pr_err("reserve failed, step %d, start %llu\n", - n, nodes[n].start); + KUNIT_FAIL(test, "reserve failed, step %d, start %llu\n", + n, nodes[n].start); ret = err; goto out; } if (!drm_mm_node_allocated(&nodes[n])) { - pr_err("reserved node not allocated! step %d, start %llu\n", - n, nodes[n].start); + KUNIT_FAIL(test, "reserved node not allocated! step %d, start %llu\n", + n, nodes[n].start); goto out; } - if (!expect_reserve_fail(&mm, &nodes[n])) + if (!expect_reserve_fail(test, &mm, &nodes[n])) goto out; } /* After random insertion the nodes should be in order */ - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; /* Repeated use should then fail */ drm_random_reorder(order, count, &prng); for (n = 0; n < count; n++) { - if (!expect_reserve_fail(&mm, - set_node(&tmp, order[n] * size, 1))) + if (!expect_reserve_fail(test, &mm, set_node(&tmp, order[n] * size, 1))) goto out; /* Remove and reinsert should work */ drm_mm_remove_node(&nodes[order[n]]); err = drm_mm_reserve_node(&mm, &nodes[order[n]]); if (err) { - pr_err("reserve failed, step %d, start %llu\n", - n, nodes[n].start); + KUNIT_FAIL(test, "reserve failed, step %d, start %llu\n", + n, nodes[n].start); ret = err; goto out; } } - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; /* Overlapping use should then fail */ for (n = 0; n < count; n++) { - if (!expect_reserve_fail(&mm, set_node(&tmp, 0, size*count))) + if (!expect_reserve_fail(test, &mm, set_node(&tmp, 0, size * count))) goto out; } for (n = 0; n < count; n++) { - if (!expect_reserve_fail(&mm, - set_node(&tmp, - size * n, - size * (count - n)))) + if (!expect_reserve_fail(test, &mm, set_node(&tmp, size * n, size * (count - n)))) goto out; } @@ -472,8 +439,8 @@ static int __igt_reserve(unsigned int count, u64 size) node = &nodes[order[(o + m) % count]]; err = drm_mm_reserve_node(&mm, node); if (err) { - pr_err("reserve failed, step %d/%d, start %llu\n", - m, n, node->start); + KUNIT_FAIL(test, "reserve failed, step %d/%d, start %llu\n", + m, n, node->start); ret = err; goto out; } @@ -481,7 +448,7 @@ static int __igt_reserve(unsigned int count, u64 size) o += n; - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; } @@ -491,41 +458,30 @@ out: drm_mm_remove_node(node); drm_mm_takedown(&mm); vfree(nodes); -err_order: kfree(order); err: return ret; } -static int igt_reserve(void *ignored) +static void igt_mm_reserve(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); - int n, ret; + int n; for_each_prime_number_from(n, 1, 54) { u64 size = BIT_ULL(n); - ret = __igt_reserve(count, size - 1); - if (ret) - return ret; - - ret = __igt_reserve(count, size); - if (ret) - return ret; - - ret = __igt_reserve(count, size + 1); - if (ret) - return ret; + KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size - 1)); + KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size)); + KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size + 1)); cond_resched(); } - - return 0; } -static bool expect_insert(struct drm_mm *mm, struct drm_mm_node *node, - u64 size, u64 alignment, unsigned long color, - const struct insert_mode *mode) +static bool expect_insert(struct kunit *test, struct drm_mm *mm, + struct drm_mm_node *node, u64 size, u64 alignment, unsigned long color, + const struct insert_mode *mode) { int err; @@ -533,12 +489,13 @@ static bool expect_insert(struct drm_mm *mm, struct drm_mm_node *node, size, alignment, color, mode->mode); if (err) { - pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) failed with err=%d\n", - size, alignment, color, mode->name, err); + KUNIT_FAIL(test, + "insert (size=%llu, alignment=%llu, color=%lu, mode=%s) failed with err=%d\n", + size, alignment, color, mode->name, err); return false; } - if (!assert_node(node, mm, size, alignment, color)) { + if (!assert_node(test, node, mm, size, alignment, color)) { drm_mm_remove_node(node); return false; } @@ -546,7 +503,7 @@ static bool expect_insert(struct drm_mm *mm, struct drm_mm_node *node, return true; } -static bool expect_insert_fail(struct drm_mm *mm, u64 size) +static bool expect_insert_fail(struct kunit *test, struct drm_mm *mm, u64 size) { struct drm_mm_node tmp = {}; int err; @@ -556,17 +513,18 @@ static bool expect_insert_fail(struct drm_mm *mm, u64 size) return true; if (!err) { - pr_err("impossible insert succeeded, node %llu + %llu\n", - tmp.start, tmp.size); + KUNIT_FAIL(test, "impossible insert succeeded, node %llu + %llu\n", + tmp.start, tmp.size); drm_mm_remove_node(&tmp); } else { - pr_err("impossible insert failed with wrong error %d [expected %d], size %llu\n", - err, -ENOSPC, size); + KUNIT_FAIL(test, + "impossible insert failed with wrong error %d [expected %d], size %llu\n", + err, -ENOSPC, size); } return false; } -static int __igt_insert(unsigned int count, u64 size, bool replace) +static int __igt_insert(struct kunit *test, unsigned int count, u64 size, bool replace) { DRM_RND_STATE(prng, random_seed); const struct insert_mode *mode; @@ -582,8 +540,7 @@ static int __igt_insert(unsigned int count, u64 size, bool replace) ret = -ENOMEM; nodes = vmalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); order = drm_random_order(count, &prng); if (!order) @@ -598,41 +555,43 @@ static int __igt_insert(unsigned int count, u64 size, bool replace) node = replace ? &tmp : &nodes[n]; memset(node, 0, sizeof(*node)); - if (!expect_insert(&mm, node, size, 0, n, mode)) { - pr_err("%s insert failed, size %llu step %d\n", - mode->name, size, n); + if (!expect_insert(test, &mm, node, size, 0, n, mode)) { + KUNIT_FAIL(test, "%s insert failed, size %llu step %d\n", + mode->name, size, n); goto out; } if (replace) { drm_mm_replace_node(&tmp, &nodes[n]); if (drm_mm_node_allocated(&tmp)) { - pr_err("replaced old-node still allocated! step %d\n", - n); + KUNIT_FAIL(test, + "replaced old-node still allocated! step %d\n", + n); goto out; } - if (!assert_node(&nodes[n], &mm, size, 0, n)) { - pr_err("replaced node did not inherit parameters, size %llu step %d\n", - size, n); + if (!assert_node(test, &nodes[n], &mm, size, 0, n)) { + KUNIT_FAIL(test, + "replaced node did not inherit parameters, size %llu step %d\n", + size, n); goto out; } if (tmp.start != nodes[n].start) { - pr_err("replaced node mismatch location expected [%llx + %llx], found [%llx + %llx]\n", - tmp.start, size, - nodes[n].start, nodes[n].size); + KUNIT_FAIL(test, + "replaced node mismatch location expected [%llx + %llx], found [%llx + %llx]\n", + tmp.start, size, nodes[n].start, nodes[n].size); goto out; } } } /* After random insertion the nodes should be in order */ - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; /* Repeated use should then fail */ - if (!expect_insert_fail(&mm, size)) + if (!expect_insert_fail(test, &mm, size)) goto out; /* Remove one and reinsert, as the only hole it should refill itself */ @@ -640,19 +599,20 @@ static int __igt_insert(unsigned int count, u64 size, bool replace) u64 addr = nodes[n].start; drm_mm_remove_node(&nodes[n]); - if (!expect_insert(&mm, &nodes[n], size, 0, n, mode)) { - pr_err("%s reinsert failed, size %llu step %d\n", - mode->name, size, n); + if (!expect_insert(test, &mm, &nodes[n], size, 0, n, mode)) { + KUNIT_FAIL(test, "%s reinsert failed, size %llu step %d\n", + mode->name, size, n); goto out; } if (nodes[n].start != addr) { - pr_err("%s reinsert node moved, step %d, expected %llx, found %llx\n", - mode->name, n, addr, nodes[n].start); + KUNIT_FAIL(test, + "%s reinsert node moved, step %d, expected %llx, found %llx\n", + mode->name, n, addr, nodes[n].start); goto out; } - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; } @@ -665,19 +625,20 @@ static int __igt_insert(unsigned int count, u64 size, bool replace) for (m = 0; m < n; m++) { node = &nodes[order[(o + m) % count]]; - if (!expect_insert(&mm, node, size, 0, n, mode)) { - pr_err("%s multiple reinsert failed, size %llu step %d\n", - mode->name, size, n); + if (!expect_insert(test, &mm, node, size, 0, n, mode)) { + KUNIT_FAIL(test, + "%s multiple reinsert failed, size %llu step %d\n", + mode->name, size, n); goto out; } } o += n; - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; - if (!expect_insert_fail(&mm, size)) + if (!expect_insert_fail(test, &mm, size)) goto out; } @@ -696,42 +657,29 @@ out: kfree(order); err_nodes: vfree(nodes); -err: return ret; } -static int igt_insert(void *ignored) +static void igt_mm_insert(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); unsigned int n; - int ret; for_each_prime_number_from(n, 1, 54) { u64 size = BIT_ULL(n); - ret = __igt_insert(count, size - 1, false); - if (ret) - return ret; - - ret = __igt_insert(count, size, false); - if (ret) - return ret; - - ret = __igt_insert(count, size + 1, false); - if (ret) - return ret; + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, false)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, false)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, false)); cond_resched(); } - - return 0; } -static int igt_replace(void *ignored) +static void igt_mm_replace(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); unsigned int n; - int ret; /* Reuse igt_insert to exercise replacement by inserting a dummy node, * then replacing it with the intended node. We want to check that @@ -742,28 +690,17 @@ static int igt_replace(void *ignored) for_each_prime_number_from(n, 1, 54) { u64 size = BIT_ULL(n); - ret = __igt_insert(count, size - 1, true); - if (ret) - return ret; - - ret = __igt_insert(count, size, true); - if (ret) - return ret; - - ret = __igt_insert(count, size + 1, true); - if (ret) - return ret; + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, true)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, true)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, true)); cond_resched(); } - - return 0; } -static bool expect_insert_in_range(struct drm_mm *mm, struct drm_mm_node *node, +static bool expect_insert_in_range(struct kunit *test, struct drm_mm *mm, struct drm_mm_node *node, u64 size, u64 alignment, unsigned long color, - u64 range_start, u64 range_end, - const struct insert_mode *mode) + u64 range_start, u64 range_end, const struct insert_mode *mode) { int err; @@ -772,13 +709,14 @@ static bool expect_insert_in_range(struct drm_mm *mm, struct drm_mm_node *node, range_start, range_end, mode->mode); if (err) { - pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) nto range [%llx, %llx] failed with err=%d\n", - size, alignment, color, mode->name, - range_start, range_end, err); + KUNIT_FAIL(test, + "insert (size=%llu, alignment=%llu, color=%lu, mode=%s) nto range [%llx, %llx] failed with err=%d\n", + size, alignment, color, mode->name, + range_start, range_end, err); return false; } - if (!assert_node(node, mm, size, alignment, color)) { + if (!assert_node(test, node, mm, size, alignment, color)) { drm_mm_remove_node(node); return false; } @@ -786,67 +724,63 @@ static bool expect_insert_in_range(struct drm_mm *mm, struct drm_mm_node *node, return true; } -static bool expect_insert_in_range_fail(struct drm_mm *mm, - u64 size, - u64 range_start, - u64 range_end) +static bool expect_insert_in_range_fail(struct kunit *test, struct drm_mm *mm, + u64 size, u64 range_start, u64 range_end) { struct drm_mm_node tmp = {}; int err; - err = drm_mm_insert_node_in_range(mm, &tmp, - size, 0, 0, - range_start, range_end, + err = drm_mm_insert_node_in_range(mm, &tmp, size, 0, 0, range_start, range_end, 0); if (likely(err == -ENOSPC)) return true; if (!err) { - pr_err("impossible insert succeeded, node %llx + %llu, range [%llx, %llx]\n", - tmp.start, tmp.size, range_start, range_end); + KUNIT_FAIL(test, + "impossible insert succeeded, node %llx + %llu, range [%llx, %llx]\n", + tmp.start, tmp.size, range_start, range_end); drm_mm_remove_node(&tmp); } else { - pr_err("impossible insert failed with wrong error %d [expected %d], size %llu, range [%llx, %llx]\n", - err, -ENOSPC, size, range_start, range_end); + KUNIT_FAIL(test, + "impossible insert failed with wrong error %d [expected %d], size %llu, range [%llx, %llx]\n", + err, -ENOSPC, size, range_start, range_end); } return false; } -static bool assert_contiguous_in_range(struct drm_mm *mm, - u64 size, - u64 start, - u64 end) +static bool assert_contiguous_in_range(struct kunit *test, struct drm_mm *mm, + u64 size, u64 start, u64 end) { struct drm_mm_node *node; unsigned int n; - if (!expect_insert_in_range_fail(mm, size, start, end)) + if (!expect_insert_in_range_fail(test, mm, size, start, end)) return false; n = div64_u64(start + size - 1, size); drm_mm_for_each_node(node, mm) { if (node->start < start || node->start + node->size > end) { - pr_err("node %d out of range, address [%llx + %llu], range [%llx, %llx]\n", - n, node->start, node->start + node->size, start, end); + KUNIT_FAIL(test, + "node %d out of range, address [%llx + %llu], range [%llx, %llx]\n", + n, node->start, node->start + node->size, start, end); return false; } if (node->start != n * size) { - pr_err("node %d out of order, expected start %llx, found %llx\n", - n, n * size, node->start); + KUNIT_FAIL(test, "node %d out of order, expected start %llx, found %llx\n", + n, n * size, node->start); return false; } if (node->size != size) { - pr_err("node %d has wrong size, expected size %llx, found %llx\n", - n, size, node->size); + KUNIT_FAIL(test, "node %d has wrong size, expected size %llx, found %llx\n", + n, size, node->size); return false; } - if (drm_mm_hole_follows(node) && - drm_mm_hole_node_end(node) < end) { - pr_err("node %d is followed by a hole!\n", n); + if (drm_mm_hole_follows(node) && drm_mm_hole_node_end(node) < end) { + KUNIT_FAIL(test, "node %d is followed by a hole!\n", n); return false; } @@ -856,8 +790,8 @@ static bool assert_contiguous_in_range(struct drm_mm *mm, if (start > 0) { node = __drm_mm_interval_first(mm, 0, start - 1); if (drm_mm_node_allocated(node)) { - pr_err("node before start: node=%llx+%llu, start=%llx\n", - node->start, node->size, start); + KUNIT_FAIL(test, "node before start: node=%llx+%llu, start=%llx\n", + node->start, node->size, start); return false; } } @@ -865,8 +799,8 @@ static bool assert_contiguous_in_range(struct drm_mm *mm, if (end < U64_MAX) { node = __drm_mm_interval_first(mm, end, U64_MAX); if (drm_mm_node_allocated(node)) { - pr_err("node after end: node=%llx+%llu, end=%llx\n", - node->start, node->size, end); + KUNIT_FAIL(test, "node after end: node=%llx+%llu, end=%llx\n", + node->start, node->size, end); return false; } } @@ -874,7 +808,7 @@ static bool assert_contiguous_in_range(struct drm_mm *mm, return true; } -static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end) +static int __igt_insert_range(struct kunit *test, unsigned int count, u64 size, u64 start, u64 end) { const struct insert_mode *mode; struct drm_mm mm; @@ -886,14 +820,13 @@ static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end) DRM_MM_BUG_ON(!size); DRM_MM_BUG_ON(end <= start); - /* Very similar to __igt_insert(), but now instead of populating the + /* Very similar to __igt_insert(struct kunit *test, ), but now instead of populating the * full range of the drm_mm, we try to fill a small portion of it. */ ret = -ENOMEM; nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); ret = -EINVAL; drm_mm_init(&mm, 0, count * size); @@ -903,20 +836,19 @@ static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end) for (mode = insert_modes; mode->name; mode++) { for (n = start_n; n <= end_n; n++) { - if (!expect_insert_in_range(&mm, &nodes[n], - size, size, n, + if (!expect_insert_in_range(test, &mm, &nodes[n], size, size, n, start, end, mode)) { - pr_err("%s insert failed, size %llu, step %d [%d, %d], range [%llx, %llx]\n", - mode->name, size, n, - start_n, end_n, - start, end); + KUNIT_FAIL(test, + "%s insert failed, size %llu, step %d [%d, %d], range [%llx, %llx]\n", + mode->name, size, n, start_n, end_n, start, end); goto out; } } - if (!assert_contiguous_in_range(&mm, size, start, end)) { - pr_err("%s: range [%llx, %llx] not full after initialisation, size=%llu\n", - mode->name, start, end, size); + if (!assert_contiguous_in_range(test, &mm, size, start, end)) { + KUNIT_FAIL(test, + "%s: range [%llx, %llx] not full after initialisation, size=%llu\n", + mode->name, start, end, size); goto out; } @@ -925,23 +857,24 @@ static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end) u64 addr = nodes[n].start; drm_mm_remove_node(&nodes[n]); - if (!expect_insert_in_range(&mm, &nodes[n], - size, size, n, + if (!expect_insert_in_range(test, &mm, &nodes[n], size, size, n, start, end, mode)) { - pr_err("%s reinsert failed, step %d\n", mode->name, n); + KUNIT_FAIL(test, "%s reinsert failed, step %d\n", mode->name, n); goto out; } if (nodes[n].start != addr) { - pr_err("%s reinsert node moved, step %d, expected %llx, found %llx\n", - mode->name, n, addr, nodes[n].start); + KUNIT_FAIL(test, + "%s reinsert node moved, step %d, expected %llx, found %llx\n", + mode->name, n, addr, nodes[n].start); goto out; } } - if (!assert_contiguous_in_range(&mm, size, start, end)) { - pr_err("%s: range [%llx, %llx] not full after reinsertion, size=%llu\n", - mode->name, start, end, size); + if (!assert_contiguous_in_range(test, &mm, size, start, end)) { + KUNIT_FAIL(test, + "%s: range [%llx, %llx] not full after reinsertion, size=%llu\n", + mode->name, start, end, size); goto out; } @@ -958,11 +891,10 @@ out: drm_mm_remove_node(node); drm_mm_takedown(&mm); vfree(nodes); -err: return ret; } -static int insert_outside_range(void) +static int insert_outside_range(struct kunit *test) { struct drm_mm mm; const unsigned int start = 1024; @@ -971,81 +903,58 @@ static int insert_outside_range(void) drm_mm_init(&mm, start, size); - if (!expect_insert_in_range_fail(&mm, 1, 0, start)) + if (!expect_insert_in_range_fail(test, &mm, 1, 0, start)) return -EINVAL; - if (!expect_insert_in_range_fail(&mm, size, - start - size/2, start + (size+1)/2)) + if (!expect_insert_in_range_fail(test, &mm, size, + start - size / 2, start + (size + 1) / 2)) return -EINVAL; - if (!expect_insert_in_range_fail(&mm, size, - end - (size+1)/2, end + size/2)) + if (!expect_insert_in_range_fail(test, &mm, size, + end - (size + 1) / 2, end + size / 2)) return -EINVAL; - if (!expect_insert_in_range_fail(&mm, 1, end, end + size)) + if (!expect_insert_in_range_fail(test, &mm, 1, end, end + size)) return -EINVAL; drm_mm_takedown(&mm); return 0; } -static int igt_insert_range(void *ignored) +static void igt_mm_insert_range(struct kunit *test) { const unsigned int count = min_t(unsigned int, BIT(13), max_iterations); unsigned int n; - int ret; /* Check that requests outside the bounds of drm_mm are rejected. */ - ret = insert_outside_range(); - if (ret) - return ret; + KUNIT_ASSERT_FALSE(test, insert_outside_range(test)); for_each_prime_number_from(n, 1, 50) { const u64 size = BIT_ULL(n); const u64 max = count * size; - ret = __igt_insert_range(count, size, 0, max); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, 1, max); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, 0, max - 1); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, 0, max/2); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, max/2, max); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, max/4+1, 3*max/4-1); - if (ret) - return ret; + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 1, max)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max - 1)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max / 2)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, max / 2, max / 2)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, + max / 4 + 1, 3 * max / 4 - 1)); cond_resched(); } - - return 0; } -static int prepare_igt_frag(struct drm_mm *mm, - struct drm_mm_node *nodes, - unsigned int num_insert, +static int prepare_igt_frag(struct kunit *test, struct drm_mm *mm, + struct drm_mm_node *nodes, unsigned int num_insert, const struct insert_mode *mode) { unsigned int size = 4096; unsigned int i; for (i = 0; i < num_insert; i++) { - if (!expect_insert(mm, &nodes[i], size, 0, i, - mode) != 0) { - pr_err("%s insert failed\n", mode->name); + if (!expect_insert(test, mm, &nodes[i], size, 0, i, mode) != 0) { + KUNIT_FAIL(test, "%s insert failed\n", mode->name); return -EINVAL; } } @@ -1057,12 +966,10 @@ static int prepare_igt_frag(struct drm_mm *mm, } return 0; - } -static u64 get_insert_time(struct drm_mm *mm, - unsigned int num_insert, - struct drm_mm_node *nodes, +static u64 get_insert_time(struct kunit *test, struct drm_mm *mm, + unsigned int num_insert, struct drm_mm_node *nodes, const struct insert_mode *mode) { unsigned int size = 8192; @@ -1071,8 +978,8 @@ static u64 get_insert_time(struct drm_mm *mm, start = ktime_get(); for (i = 0; i < num_insert; i++) { - if (!expect_insert(mm, &nodes[i], size, 0, i, mode) != 0) { - pr_err("%s insert failed\n", mode->name); + if (!expect_insert(test, mm, &nodes[i], size, 0, i, mode) != 0) { + KUNIT_FAIL(test, "%s insert failed\n", mode->name); return 0; } } @@ -1080,28 +987,26 @@ static u64 get_insert_time(struct drm_mm *mm, return ktime_to_ns(ktime_sub(ktime_get(), start)); } -static int igt_frag(void *ignored) +static void igt_mm_frag(struct kunit *test) { struct drm_mm mm; const struct insert_mode *mode; struct drm_mm_node *nodes, *node, *next; unsigned int insert_size = 10000; unsigned int scale_factor = 4; - int ret = -EINVAL; /* We need 4 * insert_size nodes to hold intermediate allocated * drm_mm nodes. - * 1 times for prepare_igt_frag() - * 1 times for get_insert_time() - * 2 times for get_insert_time() + * 1 times for prepare_igt_frag(struct kunit *test, ) + * 1 times for get_insert_time(struct kunit *test, ) + * 2 times for get_insert_time(struct kunit *test, ) */ nodes = vzalloc(array_size(insert_size * 4, sizeof(*nodes))); - if (!nodes) - return -ENOMEM; + KUNIT_ASSERT_TRUE(test, nodes); /* For BOTTOMUP and TOPDOWN, we first fragment the - * address space using prepare_igt_frag() and then try to verify - * that that insertions scale quadratically from 10k to 20k insertions + * address space using prepare_igt_frag(struct kunit *test, ) and then try to verify + * that insertions scale quadratically from 10k to 20k insertions */ drm_mm_init(&mm, 1, U64_MAX - 2); for (mode = insert_modes; mode->name; mode++) { @@ -1111,28 +1016,25 @@ static int igt_frag(void *ignored) mode->mode != DRM_MM_INSERT_HIGH) continue; - ret = prepare_igt_frag(&mm, nodes, insert_size, mode); - if (ret) + if (prepare_igt_frag(test, &mm, nodes, insert_size, mode)) goto err; - insert_time1 = get_insert_time(&mm, insert_size, + insert_time1 = get_insert_time(test, &mm, insert_size, nodes + insert_size, mode); if (insert_time1 == 0) goto err; - insert_time2 = get_insert_time(&mm, (insert_size * 2), + insert_time2 = get_insert_time(test, &mm, (insert_size * 2), nodes + insert_size * 2, mode); if (insert_time2 == 0) goto err; - pr_info("%s fragmented insert of %u and %u insertions took %llu and %llu nsecs\n", - mode->name, insert_size, insert_size * 2, - insert_time1, insert_time2); + kunit_info(test, "%s fragmented insert of %u and %u insertions took %llu and %llu nsecs\n", + mode->name, insert_size, insert_size * 2, insert_time1, insert_time2); if (insert_time2 > (scale_factor * insert_time1)) { - pr_err("%s fragmented insert took %llu nsecs more\n", - mode->name, - insert_time2 - (scale_factor * insert_time1)); + KUNIT_FAIL(test, "%s fragmented insert took %llu nsecs more\n", + mode->name, insert_time2 - (scale_factor * insert_time1)); goto err; } @@ -1140,24 +1042,20 @@ static int igt_frag(void *ignored) drm_mm_remove_node(node); } - ret = 0; err: drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); drm_mm_takedown(&mm); vfree(nodes); - - return ret; } -static int igt_align(void *ignored) +static void igt_mm_align(struct kunit *test) { const struct insert_mode *mode; const unsigned int max_count = min(8192u, max_prime); struct drm_mm mm; struct drm_mm_node *nodes, *node, *next; unsigned int prime; - int ret = -EINVAL; /* For each of the possible insertion modes, we pick a few * arbitrary alignments and check that the inserted node @@ -1165,8 +1063,7 @@ static int igt_align(void *ignored) */ nodes = vzalloc(array_size(max_count, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); drm_mm_init(&mm, 1, U64_MAX - 2); @@ -1176,11 +1073,9 @@ static int igt_align(void *ignored) for_each_prime_number_from(prime, 1, max_count) { u64 size = next_prime_number(prime); - if (!expect_insert(&mm, &nodes[i], - size, prime, i, - mode)) { - pr_err("%s insert failed with alignment=%d", - mode->name, prime); + if (!expect_insert(test, &mm, &nodes[i], size, prime, i, mode)) { + KUNIT_FAIL(test, "%s insert failed with alignment=%d", + mode->name, prime); goto out; } @@ -1194,22 +1089,18 @@ static int igt_align(void *ignored) cond_resched(); } - ret = 0; out: drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); drm_mm_takedown(&mm); vfree(nodes); -err: - return ret; } -static int igt_align_pot(int max) +static void igt_align_pot(struct kunit *test, int max) { struct drm_mm mm; struct drm_mm_node *node, *next; int bit; - int ret = -EINVAL; /* Check that we can align to the full u64 address space */ @@ -1220,51 +1111,45 @@ static int igt_align_pot(int max) node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) { - ret = -ENOMEM; + KUNIT_FAIL(test, "failed to allocate node"); goto out; } align = BIT_ULL(bit); - size = BIT_ULL(bit-1) + 1; - if (!expect_insert(&mm, node, - size, align, bit, - &insert_modes[0])) { - pr_err("insert failed with alignment=%llx [%d]", - align, bit); + size = BIT_ULL(bit - 1) + 1; + if (!expect_insert(test, &mm, node, size, align, bit, &insert_modes[0])) { + KUNIT_FAIL(test, "insert failed with alignment=%llx [%d]", align, bit); goto out; } cond_resched(); } - ret = 0; out: drm_mm_for_each_node_safe(node, next, &mm) { drm_mm_remove_node(node); kfree(node); } drm_mm_takedown(&mm); - return ret; } -static int igt_align32(void *ignored) +static void igt_mm_align32(struct kunit *test) { - return igt_align_pot(32); + igt_align_pot(test, 32); } -static int igt_align64(void *ignored) +static void igt_mm_align64(struct kunit *test) { - return igt_align_pot(64); + igt_align_pot(test, 64); } -static void show_scan(const struct drm_mm_scan *scan) +static void show_scan(struct kunit *test, const struct drm_mm_scan *scan) { - pr_info("scan: hit [%llx, %llx], size=%lld, align=%lld, color=%ld\n", - scan->hit_start, scan->hit_end, - scan->size, scan->alignment, scan->color); + kunit_info(test, "scan: hit [%llx, %llx], size=%lld, align=%lld, color=%ld\n", + scan->hit_start, scan->hit_end, scan->size, scan->alignment, scan->color); } -static void show_holes(const struct drm_mm *mm, int count) +static void show_holes(struct kunit *test, const struct drm_mm *mm, int count) { u64 hole_start, hole_end; struct drm_mm_node *hole; @@ -1274,19 +1159,15 @@ static void show_holes(const struct drm_mm *mm, int count) const char *node1 = NULL, *node2 = NULL; if (drm_mm_node_allocated(hole)) - node1 = kasprintf(GFP_KERNEL, - "[%llx + %lld, color=%ld], ", + node1 = kasprintf(GFP_KERNEL, "[%llx + %lld, color=%ld], ", hole->start, hole->size, hole->color); if (drm_mm_node_allocated(next)) - node2 = kasprintf(GFP_KERNEL, - ", [%llx + %lld, color=%ld]", + node2 = kasprintf(GFP_KERNEL, ", [%llx + %lld, color=%ld]", next->start, next->size, next->color); - pr_info("%sHole [%llx - %llx, size %lld]%s\n", - node1, - hole_start, hole_end, hole_end - hole_start, - node2); + kunit_info(test, "%sHole [%llx - %llx, size %lld]%s\n", node1, + hole_start, hole_end, hole_end - hole_start, node2); kfree(node2); kfree(node1); @@ -1301,12 +1182,9 @@ struct evict_node { struct list_head link; }; -static bool evict_nodes(struct drm_mm_scan *scan, - struct evict_node *nodes, - unsigned int *order, - unsigned int count, - bool use_color, - struct list_head *evict_list) +static bool evict_nodes(struct kunit *test, struct drm_mm_scan *scan, + struct evict_node *nodes, unsigned int *order, unsigned int count, + bool use_color, struct list_head *evict_list) { struct evict_node *e, *en; unsigned int i; @@ -1322,8 +1200,9 @@ static bool evict_nodes(struct drm_mm_scan *scan, list_del(&e->link); } if (list_empty(evict_list)) { - pr_err("Failed to find eviction: size=%lld [avail=%d], align=%lld (color=%lu)\n", - scan->size, count, scan->alignment, scan->color); + KUNIT_FAIL(test, + "Failed to find eviction: size=%lld [avail=%d], align=%lld (color=%lu)\n", + scan->size, count, scan->alignment, scan->color); return false; } @@ -1340,7 +1219,8 @@ static bool evict_nodes(struct drm_mm_scan *scan, } } else { if (drm_mm_scan_color_evict(scan)) { - pr_err("drm_mm_scan_color_evict unexpectedly reported overlapping nodes!\n"); + KUNIT_FAIL(test, + "drm_mm_scan_color_evict unexpectedly reported overlapping nodes!\n"); return false; } } @@ -1348,9 +1228,8 @@ static bool evict_nodes(struct drm_mm_scan *scan, return true; } -static bool evict_nothing(struct drm_mm *mm, - unsigned int total_size, - struct evict_node *nodes) +static bool evict_nothing(struct kunit *test, struct drm_mm *mm, + unsigned int total_size, struct evict_node *nodes) { struct drm_mm_scan scan; LIST_HEAD(evict_list); @@ -1371,7 +1250,7 @@ static bool evict_nothing(struct drm_mm *mm, e = &nodes[n]; if (!drm_mm_node_allocated(&e->node)) { - pr_err("node[%d] no longer allocated!\n", n); + KUNIT_FAIL(test, "node[%d] no longer allocated!\n", n); return false; } @@ -1387,17 +1266,16 @@ static bool evict_nothing(struct drm_mm *mm, e = &nodes[n]; if (!e->link.next) { - pr_err("node[%d] no longer connected!\n", n); + KUNIT_FAIL(test, "node[%d] no longer connected!\n", n); return false; } } - return assert_continuous(mm, nodes[0].node.size); + return assert_continuous(test, mm, nodes[0].node.size); } -static bool evict_everything(struct drm_mm *mm, - unsigned int total_size, - struct evict_node *nodes) +static bool evict_everything(struct kunit *test, struct drm_mm *mm, + unsigned int total_size, struct evict_node *nodes) { struct drm_mm_scan scan; LIST_HEAD(evict_list); @@ -1417,8 +1295,8 @@ static bool evict_everything(struct drm_mm *mm, list_for_each_entry(e, &evict_list, link) { if (!drm_mm_scan_remove_block(&scan, &e->node)) { if (!err) { - pr_err("Node %lld not marked for eviction!\n", - e->node.start); + KUNIT_FAIL(test, "Node %lld not marked for eviction!\n", + e->node.start); err = -EINVAL; } } @@ -1429,29 +1307,25 @@ static bool evict_everything(struct drm_mm *mm, list_for_each_entry(e, &evict_list, link) drm_mm_remove_node(&e->node); - if (!assert_one_hole(mm, 0, total_size)) + if (!assert_one_hole(test, mm, 0, total_size)) return false; list_for_each_entry(e, &evict_list, link) { err = drm_mm_reserve_node(mm, &e->node); if (err) { - pr_err("Failed to reinsert node after eviction: start=%llx\n", - e->node.start); + KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n", + e->node.start); return false; } } - return assert_continuous(mm, nodes[0].node.size); + return assert_continuous(test, mm, nodes[0].node.size); } -static int evict_something(struct drm_mm *mm, - u64 range_start, u64 range_end, - struct evict_node *nodes, - unsigned int *order, - unsigned int count, - unsigned int size, - unsigned int alignment, - const struct insert_mode *mode) +static int evict_something(struct kunit *test, struct drm_mm *mm, + u64 range_start, u64 range_end, struct evict_node *nodes, + unsigned int *order, unsigned int count, unsigned int size, + unsigned int alignment, const struct insert_mode *mode) { struct drm_mm_scan scan; LIST_HEAD(evict_list); @@ -1459,38 +1333,35 @@ static int evict_something(struct drm_mm *mm, struct drm_mm_node tmp; int err; - drm_mm_scan_init_with_range(&scan, mm, - size, alignment, 0, - range_start, range_end, - mode->mode); - if (!evict_nodes(&scan, - nodes, order, count, false, - &evict_list)) + drm_mm_scan_init_with_range(&scan, mm, size, alignment, 0, range_start, + range_end, mode->mode); + if (!evict_nodes(test, &scan, nodes, order, count, false, &evict_list)) return -EINVAL; memset(&tmp, 0, sizeof(tmp)); err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, 0, DRM_MM_INSERT_EVICT); if (err) { - pr_err("Failed to insert into eviction hole: size=%d, align=%d\n", - size, alignment); - show_scan(&scan); - show_holes(mm, 3); + KUNIT_FAIL(test, "Failed to insert into eviction hole: size=%d, align=%d\n", + size, alignment); + show_scan(test, &scan); + show_holes(test, mm, 3); return err; } if (tmp.start < range_start || tmp.start + tmp.size > range_end) { - pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", - tmp.start, tmp.size, range_start, range_end); + KUNIT_FAIL(test, + "Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", + tmp.start, tmp.size, range_start, range_end); err = -EINVAL; } - if (!assert_node(&tmp, mm, size, alignment, 0) || + if (!assert_node(test, &tmp, mm, size, alignment, 0) || drm_mm_hole_follows(&tmp)) { - pr_err("Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n", - tmp.size, size, - alignment, misalignment(&tmp, alignment), - tmp.start, drm_mm_hole_follows(&tmp)); + KUNIT_FAIL(test, + "Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n", + tmp.size, size, alignment, misalignment(&tmp, alignment), + tmp.start, drm_mm_hole_follows(&tmp)); err = -EINVAL; } @@ -1501,21 +1372,21 @@ static int evict_something(struct drm_mm *mm, list_for_each_entry(e, &evict_list, link) { err = drm_mm_reserve_node(mm, &e->node); if (err) { - pr_err("Failed to reinsert node after eviction: start=%llx\n", - e->node.start); + KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n", + e->node.start); return err; } } - if (!assert_continuous(mm, nodes[0].node.size)) { - pr_err("range is no longer continuous\n"); + if (!assert_continuous(test, mm, nodes[0].node.size)) { + KUNIT_FAIL(test, "range is no longer continuous\n"); return -EINVAL; } return 0; } -static int igt_evict(void *ignored) +static void igt_mm_evict(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int size = 8192; @@ -1524,7 +1395,6 @@ static int igt_evict(void *ignored) struct evict_node *nodes; struct drm_mm_node *node, *next; unsigned int *order, n; - int ret, err; /* Here we populate a full drm_mm and then try and insert a new node * by evicting other nodes in a random order. The drm_mm_scan should @@ -1533,61 +1403,49 @@ static int igt_evict(void *ignored) * sizes to try and stress the hole finder. */ - ret = -ENOMEM; nodes = vzalloc(array_size(size, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); order = drm_random_order(size, &prng); if (!order) goto err_nodes; - ret = -EINVAL; drm_mm_init(&mm, 0, size); for (n = 0; n < size; n++) { - err = drm_mm_insert_node(&mm, &nodes[n].node, 1); - if (err) { - pr_err("insert failed, step %d\n", n); - ret = err; + if (drm_mm_insert_node(&mm, &nodes[n].node, 1)) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); goto out; } } /* First check that using the scanner doesn't break the mm */ - if (!evict_nothing(&mm, size, nodes)) { - pr_err("evict_nothing() failed\n"); + if (!evict_nothing(test, &mm, size, nodes)) { + KUNIT_FAIL(test, "evict_nothing() failed\n"); goto out; } - if (!evict_everything(&mm, size, nodes)) { - pr_err("evict_everything() failed\n"); + if (!evict_everything(test, &mm, size, nodes)) { + KUNIT_FAIL(test, "evict_everything() failed\n"); goto out; } for (mode = evict_modes; mode->name; mode++) { for (n = 1; n <= size; n <<= 1) { drm_random_reorder(order, size, &prng); - err = evict_something(&mm, 0, U64_MAX, - nodes, order, size, - n, 1, - mode); - if (err) { - pr_err("%s evict_something(size=%u) failed\n", - mode->name, n); - ret = err; + if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size, n, 1, + mode)) { + KUNIT_FAIL(test, "%s evict_something(size=%u) failed\n", + mode->name, n); goto out; } } for (n = 1; n < size; n <<= 1) { drm_random_reorder(order, size, &prng); - err = evict_something(&mm, 0, U64_MAX, - nodes, order, size, - size/2, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed\n", - mode->name, size/2, n); - ret = err; + if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size, + size / 2, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed\n", + mode->name, size / 2, n); goto out; } } @@ -1598,14 +1456,11 @@ static int igt_evict(void *ignored) DRM_MM_BUG_ON(!nsize); drm_random_reorder(order, size, &prng); - err = evict_something(&mm, 0, U64_MAX, - nodes, order, size, - nsize, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed\n", - mode->name, nsize, n); - ret = err; + if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size, + nsize, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed\n", + mode->name, nsize, n); goto out; } } @@ -1613,7 +1468,6 @@ static int igt_evict(void *ignored) cond_resched(); } - ret = 0; out: drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); @@ -1621,11 +1475,9 @@ out: kfree(order); err_nodes: vfree(nodes); -err: - return ret; } -static int igt_evict_range(void *ignored) +static void igt_mm_evict_range(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int size = 8192; @@ -1637,28 +1489,22 @@ static int igt_evict_range(void *ignored) struct evict_node *nodes; struct drm_mm_node *node, *next; unsigned int *order, n; - int ret, err; /* Like igt_evict() but now we are limiting the search to a * small portion of the full drm_mm. */ - ret = -ENOMEM; nodes = vzalloc(array_size(size, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); order = drm_random_order(size, &prng); if (!order) goto err_nodes; - ret = -EINVAL; drm_mm_init(&mm, 0, size); for (n = 0; n < size; n++) { - err = drm_mm_insert_node(&mm, &nodes[n].node, 1); - if (err) { - pr_err("insert failed, step %d\n", n); - ret = err; + if (drm_mm_insert_node(&mm, &nodes[n].node, 1)) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); goto out; } } @@ -1666,26 +1512,22 @@ static int igt_evict_range(void *ignored) for (mode = evict_modes; mode->name; mode++) { for (n = 1; n <= range_size; n <<= 1) { drm_random_reorder(order, size, &prng); - err = evict_something(&mm, range_start, range_end, - nodes, order, size, - n, 1, - mode); - if (err) { - pr_err("%s evict_something(size=%u) failed with range [%u, %u]\n", - mode->name, n, range_start, range_end); + if (evict_something(test, &mm, range_start, range_end, nodes, + order, size, n, 1, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u) failed with range [%u, %u]\n", + mode->name, n, range_start, range_end); goto out; } } for (n = 1; n <= range_size; n <<= 1) { drm_random_reorder(order, size, &prng); - err = evict_something(&mm, range_start, range_end, - nodes, order, size, - range_size/2, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", - mode->name, range_size/2, n, range_start, range_end); + if (evict_something(test, &mm, range_start, range_end, nodes, + order, size, range_size / 2, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", + mode->name, range_size / 2, n, range_start, range_end); goto out; } } @@ -1696,13 +1538,11 @@ static int igt_evict_range(void *ignored) DRM_MM_BUG_ON(!nsize); drm_random_reorder(order, size, &prng); - err = evict_something(&mm, range_start, range_end, - nodes, order, size, - nsize, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", - mode->name, nsize, n, range_start, range_end); + if (evict_something(test, &mm, range_start, range_end, nodes, + order, size, nsize, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", + mode->name, nsize, n, range_start, range_end); goto out; } } @@ -1710,7 +1550,6 @@ static int igt_evict_range(void *ignored) cond_resched(); } - ret = 0; out: drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); @@ -1718,8 +1557,6 @@ out: kfree(order); err_nodes: vfree(nodes); -err: - return ret; } static unsigned int node_index(const struct drm_mm_node *node) @@ -1727,9 +1564,10 @@ static unsigned int node_index(const struct drm_mm_node *node) return div64_u64(node->start, node->size); } -static int igt_topdown(void *ignored) +static void igt_mm_topdown(struct kunit *test) { const struct insert_mode *topdown = &insert_modes[TOPDOWN]; + DRM_RND_STATE(prng, random_seed); const unsigned int count = 8192; unsigned int size; @@ -1737,17 +1575,14 @@ static int igt_topdown(void *ignored) struct drm_mm mm; struct drm_mm_node *nodes, *node, *next; unsigned int *order, n, m, o = 0; - int ret; /* When allocating top-down, we expect to be returned a node * from a suitable hole at the top of the drm_mm. We check that * the returned node does match the highest available slot. */ - ret = -ENOMEM; nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); bitmap = bitmap_zalloc(count, GFP_KERNEL); if (!bitmap) @@ -1757,28 +1592,26 @@ static int igt_topdown(void *ignored) if (!order) goto err_bitmap; - ret = -EINVAL; for (size = 1; size <= 64; size <<= 1) { - drm_mm_init(&mm, 0, size*count); + drm_mm_init(&mm, 0, size * count); for (n = 0; n < count; n++) { - if (!expect_insert(&mm, &nodes[n], - size, 0, n, - topdown)) { - pr_err("insert failed, size %u step %d\n", size, n); + if (!expect_insert(test, &mm, &nodes[n], size, 0, n, topdown)) { + KUNIT_FAIL(test, "insert failed, size %u step %d\n", size, n); goto out; } if (drm_mm_hole_follows(&nodes[n])) { - pr_err("hole after topdown insert %d, start=%llx\n, size=%u", - n, nodes[n].start, size); + KUNIT_FAIL(test, + "hole after topdown insert %d, start=%llx\n, size=%u", + n, nodes[n].start, size); goto out; } - if (!assert_one_hole(&mm, 0, size*(count - n - 1))) + if (!assert_one_hole(test, &mm, 0, size * (count - n - 1))) goto out; } - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; drm_random_reorder(order, count, &prng); @@ -1793,23 +1626,23 @@ static int igt_topdown(void *ignored) unsigned int last; node = &nodes[order[(o + m) % count]]; - if (!expect_insert(&mm, node, - size, 0, 0, - topdown)) { - pr_err("insert failed, step %d/%d\n", m, n); + if (!expect_insert(test, &mm, node, size, 0, 0, topdown)) { + KUNIT_FAIL(test, "insert failed, step %d/%d\n", m, n); goto out; } if (drm_mm_hole_follows(node)) { - pr_err("hole after topdown insert %d/%d, start=%llx\n", - m, n, node->start); + KUNIT_FAIL(test, + "hole after topdown insert %d/%d, start=%llx\n", + m, n, node->start); goto out; } last = find_last_bit(bitmap, count); if (node_index(node) != last) { - pr_err("node %d/%d, size %d, not inserted into upmost hole, expected %d, found %d\n", - m, n, size, last, node_index(node)); + KUNIT_FAIL(test, + "node %d/%d, size %d, not inserted into upmost hole, expected %d, found %d\n", + m, n, size, last, node_index(node)); goto out; } @@ -1827,7 +1660,6 @@ static int igt_topdown(void *ignored) cond_resched(); } - ret = 0; out: drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); @@ -1837,13 +1669,12 @@ err_bitmap: bitmap_free(bitmap); err_nodes: vfree(nodes); -err: - return ret; } -static int igt_bottomup(void *ignored) +static void igt_mm_bottomup(struct kunit *test) { const struct insert_mode *bottomup = &insert_modes[BOTTOMUP]; + DRM_RND_STATE(prng, random_seed); const unsigned int count = 8192; unsigned int size; @@ -1851,16 +1682,13 @@ static int igt_bottomup(void *ignored) struct drm_mm mm; struct drm_mm_node *nodes, *node, *next; unsigned int *order, n, m, o = 0; - int ret; /* Like igt_topdown, but instead of searching for the last hole, * we search for the first. */ - ret = -ENOMEM; nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); bitmap = bitmap_zalloc(count, GFP_KERNEL); if (!bitmap) @@ -1870,22 +1698,20 @@ static int igt_bottomup(void *ignored) if (!order) goto err_bitmap; - ret = -EINVAL; for (size = 1; size <= 64; size <<= 1) { - drm_mm_init(&mm, 0, size*count); + drm_mm_init(&mm, 0, size * count); for (n = 0; n < count; n++) { - if (!expect_insert(&mm, &nodes[n], - size, 0, n, - bottomup)) { - pr_err("bottomup insert failed, size %u step %d\n", size, n); + if (!expect_insert(test, &mm, &nodes[n], size, 0, n, bottomup)) { + KUNIT_FAIL(test, + "bottomup insert failed, size %u step %d\n", size, n); goto out; } - if (!assert_one_hole(&mm, size*(n + 1), size*count)) + if (!assert_one_hole(test, &mm, size * (n + 1), size * count)) goto out; } - if (!assert_continuous(&mm, size)) + if (!assert_continuous(test, &mm, size)) goto out; drm_random_reorder(order, count, &prng); @@ -1900,17 +1726,16 @@ static int igt_bottomup(void *ignored) unsigned int first; node = &nodes[order[(o + m) % count]]; - if (!expect_insert(&mm, node, - size, 0, 0, - bottomup)) { - pr_err("insert failed, step %d/%d\n", m, n); + if (!expect_insert(test, &mm, node, size, 0, 0, bottomup)) { + KUNIT_FAIL(test, "insert failed, step %d/%d\n", m, n); goto out; } first = find_first_bit(bitmap, count); if (node_index(node) != first) { - pr_err("node %d/%d not inserted into bottom hole, expected %d, found %d\n", - m, n, first, node_index(node)); + KUNIT_FAIL(test, + "node %d/%d not inserted into bottom hole, expected %d, found %d\n", + m, n, first, node_index(node)); goto out; } __clear_bit(first, bitmap); @@ -1927,7 +1752,6 @@ static int igt_bottomup(void *ignored) cond_resched(); } - ret = 0; out: drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); @@ -1937,47 +1761,39 @@ err_bitmap: bitmap_free(bitmap); err_nodes: vfree(nodes); -err: - return ret; } -static int __igt_once(unsigned int mode) +static void __igt_once(struct kunit *test, unsigned int mode) { struct drm_mm mm; struct drm_mm_node rsvd_lo, rsvd_hi, node; - int err; drm_mm_init(&mm, 0, 7); memset(&rsvd_lo, 0, sizeof(rsvd_lo)); rsvd_lo.start = 1; rsvd_lo.size = 1; - err = drm_mm_reserve_node(&mm, &rsvd_lo); - if (err) { - pr_err("Could not reserve low node\n"); + if (drm_mm_reserve_node(&mm, &rsvd_lo)) { + KUNIT_FAIL(test, "Could not reserve low node\n"); goto err; } memset(&rsvd_hi, 0, sizeof(rsvd_hi)); rsvd_hi.start = 5; rsvd_hi.size = 1; - err = drm_mm_reserve_node(&mm, &rsvd_hi); - if (err) { - pr_err("Could not reserve low node\n"); + if (drm_mm_reserve_node(&mm, &rsvd_hi)) { + KUNIT_FAIL(test, "Could not reserve low node\n"); goto err_lo; } if (!drm_mm_hole_follows(&rsvd_lo) || !drm_mm_hole_follows(&rsvd_hi)) { - pr_err("Expected a hole after lo and high nodes!\n"); - err = -EINVAL; + KUNIT_FAIL(test, "Expected a hole after lo and high nodes!\n"); goto err_hi; } memset(&node, 0, sizeof(node)); - err = drm_mm_insert_node_generic(&mm, &node, 2, 0, 0, mode); - if (err) { - pr_err("Could not insert the node into the available hole!\n"); - err = -EINVAL; + if (drm_mm_insert_node_generic(&mm, &node, 2, 0, 0, mode)) { + KUNIT_FAIL(test, "Could not insert the node into the available hole!\n"); goto err_hi; } @@ -1988,23 +1804,20 @@ err_lo: drm_mm_remove_node(&rsvd_lo); err: drm_mm_takedown(&mm); - return err; } -static int igt_lowest(void *ignored) +static void igt_mm_lowest(struct kunit *test) { - return __igt_once(DRM_MM_INSERT_LOW); + __igt_once(test, DRM_MM_INSERT_LOW); } -static int igt_highest(void *ignored) +static void igt_mm_highest(struct kunit *test) { - return __igt_once(DRM_MM_INSERT_HIGH); + __igt_once(test, DRM_MM_INSERT_HIGH); } static void separate_adjacent_colors(const struct drm_mm_node *node, - unsigned long color, - u64 *start, - u64 *end) + unsigned long color, u64 *start, u64 *end) { if (drm_mm_node_allocated(node) && node->color != color) ++*start; @@ -2014,12 +1827,12 @@ static void separate_adjacent_colors(const struct drm_mm_node *node, --*end; } -static bool colors_abutt(const struct drm_mm_node *node) +static bool colors_abutt(struct kunit *test, const struct drm_mm_node *node) { if (!drm_mm_hole_follows(node) && drm_mm_node_allocated(list_next_entry(node, node_list))) { - pr_err("colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n", - node->color, node->start, node->size, + KUNIT_FAIL(test, "colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n", + node->color, node->start, node->size, list_next_entry(node, node_list)->color, list_next_entry(node, node_list)->start, list_next_entry(node, node_list)->size); @@ -2029,14 +1842,13 @@ static bool colors_abutt(const struct drm_mm_node *node) return false; } -static int igt_color(void *ignored) +static void igt_mm_color(struct kunit *test) { const unsigned int count = min(4096u, max_iterations); const struct insert_mode *mode; struct drm_mm mm; struct drm_mm_node *node, *nn; unsigned int n; - int ret = -EINVAL, err; /* Color adjustment complicates everything. First we just check * that when we insert a node we apply any color_adjustment callback. @@ -2049,15 +1861,11 @@ static int igt_color(void *ignored) for (n = 1; n <= count; n++) { node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; + if (!node) goto out; - } - if (!expect_insert(&mm, node, - n, 0, n, - &insert_modes[0])) { - pr_err("insert failed, step %d\n", n); + if (!expect_insert(test, &mm, node, n, 0, n, &insert_modes[0])) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); kfree(node); goto out; } @@ -2065,8 +1873,8 @@ static int igt_color(void *ignored) drm_mm_for_each_node_safe(node, nn, &mm) { if (node->color != node->size) { - pr_err("invalid color stored: expected %lld, found %ld\n", - node->size, node->color); + KUNIT_FAIL(test, "invalid color stored: expected %lld, found %ld\n", + node->size, node->color); goto out; } @@ -2081,18 +1889,14 @@ static int igt_color(void *ignored) u64 last; node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; + if (!node) goto out; - } - node->size = 1 + 2*count; + node->size = 1 + 2 * count; node->color = node->size; - err = drm_mm_reserve_node(&mm, node); - if (err) { - pr_err("initial reserve failed!\n"); - ret = err; + if (drm_mm_reserve_node(&mm, node)) { + KUNIT_FAIL(test, "initial reserve failed!\n"); goto out; } @@ -2102,19 +1906,15 @@ static int igt_color(void *ignored) int rem; node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; + if (!node) goto out; - } node->start = last; node->size = n + count; node->color = node->size; - err = drm_mm_reserve_node(&mm, node); - if (err != -ENOSPC) { - pr_err("reserve %d did not report color overlap! err=%d\n", - n, err); + if (drm_mm_reserve_node(&mm, node) != -ENOSPC) { + KUNIT_FAIL(test, "reserve %d did not report color overlap!", n); goto out; } @@ -2122,10 +1922,8 @@ static int igt_color(void *ignored) rem = misalignment(node, n + count); node->start += n + count - rem; - err = drm_mm_reserve_node(&mm, node); - if (err) { - pr_err("reserve %d failed, err=%d\n", n, err); - ret = err; + if (drm_mm_reserve_node(&mm, node)) { + KUNIT_FAIL(test, "reserve %d failed", n); goto out; } @@ -2134,16 +1932,11 @@ static int igt_color(void *ignored) for (n = 1; n <= count; n++) { node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; + if (!node) goto out; - } - if (!expect_insert(&mm, node, - n, n, n, - mode)) { - pr_err("%s insert failed, step %d\n", - mode->name, n); + if (!expect_insert(test, &mm, node, n, n, n, mode)) { + KUNIT_FAIL(test, "%s insert failed, step %d\n", mode->name, n); kfree(node); goto out; } @@ -2153,19 +1946,21 @@ static int igt_color(void *ignored) u64 rem; if (node->color != node->size) { - pr_err("%s invalid color stored: expected %lld, found %ld\n", - mode->name, node->size, node->color); + KUNIT_FAIL(test, + "%s invalid color stored: expected %lld, found %ld\n", + mode->name, node->size, node->color); goto out; } - if (colors_abutt(node)) + if (colors_abutt(test, node)) goto out; div64_u64_rem(node->start, node->size, &rem); if (rem) { - pr_err("%s colored node misaligned, start=%llx expected alignment=%lld [rem=%lld]\n", - mode->name, node->start, node->size, rem); + KUNIT_FAIL(test, + "%s colored node misaligned, start=%llx expected alignment=%lld [rem=%lld]\n", + mode->name, node->start, node->size, rem); goto out; } @@ -2176,25 +1971,18 @@ static int igt_color(void *ignored) cond_resched(); } - ret = 0; out: drm_mm_for_each_node_safe(node, nn, &mm) { drm_mm_remove_node(node); kfree(node); } drm_mm_takedown(&mm); - return ret; } -static int evict_color(struct drm_mm *mm, - u64 range_start, u64 range_end, - struct evict_node *nodes, - unsigned int *order, - unsigned int count, - unsigned int size, - unsigned int alignment, - unsigned long color, - const struct insert_mode *mode) +static int evict_color(struct kunit *test, struct drm_mm *mm, u64 range_start, + u64 range_end, struct evict_node *nodes, unsigned int *order, + unsigned int count, unsigned int size, unsigned int alignment, + unsigned long color, const struct insert_mode *mode) { struct drm_mm_scan scan; LIST_HEAD(evict_list); @@ -2202,39 +1990,37 @@ static int evict_color(struct drm_mm *mm, struct drm_mm_node tmp; int err; - drm_mm_scan_init_with_range(&scan, mm, - size, alignment, color, - range_start, range_end, - mode->mode); - if (!evict_nodes(&scan, - nodes, order, count, true, - &evict_list)) + drm_mm_scan_init_with_range(&scan, mm, size, alignment, color, range_start, + range_end, mode->mode); + if (!evict_nodes(test, &scan, nodes, order, count, true, &evict_list)) return -EINVAL; memset(&tmp, 0, sizeof(tmp)); err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, color, DRM_MM_INSERT_EVICT); if (err) { - pr_err("Failed to insert into eviction hole: size=%d, align=%d, color=%lu, err=%d\n", - size, alignment, color, err); - show_scan(&scan); - show_holes(mm, 3); + KUNIT_FAIL(test, + "Failed to insert into eviction hole: size=%d, align=%d, color=%lu, err=%d\n", + size, alignment, color, err); + show_scan(test, &scan); + show_holes(test, mm, 3); return err; } if (tmp.start < range_start || tmp.start + tmp.size > range_end) { - pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", - tmp.start, tmp.size, range_start, range_end); + KUNIT_FAIL(test, + "Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", + tmp.start, tmp.size, range_start, range_end); err = -EINVAL; } - if (colors_abutt(&tmp)) + if (colors_abutt(test, &tmp)) err = -EINVAL; - if (!assert_node(&tmp, mm, size, alignment, color)) { - pr_err("Inserted did not fit the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx\n", - tmp.size, size, - alignment, misalignment(&tmp, alignment), tmp.start); + if (!assert_node(test, &tmp, mm, size, alignment, color)) { + KUNIT_FAIL(test, + "Inserted did not fit the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx\n", + tmp.size, size, alignment, misalignment(&tmp, alignment), tmp.start); err = -EINVAL; } @@ -2245,8 +2031,8 @@ static int evict_color(struct drm_mm *mm, list_for_each_entry(e, &evict_list, link) { err = drm_mm_reserve_node(mm, &e->node); if (err) { - pr_err("Failed to reinsert node after eviction: start=%llx\n", - e->node.start); + KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n", + e->node.start); return err; } } @@ -2255,7 +2041,7 @@ static int evict_color(struct drm_mm *mm, return 0; } -static int igt_color_evict(void *ignored) +static void igt_mm_color_evict(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int total_size = min(8192u, max_iterations); @@ -2265,7 +2051,6 @@ static int igt_color_evict(void *ignored) struct evict_node *nodes; struct drm_mm_node *node, *next; unsigned int *order, n; - int ret, err; /* Check that the drm_mm_scan also honours color adjustment when * choosing its victims to create a hole. Our color_adjust does not @@ -2273,23 +2058,20 @@ static int igt_color_evict(void *ignored) * enlarging the set of victims that must be evicted. */ - ret = -ENOMEM; nodes = vzalloc(array_size(total_size, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); order = drm_random_order(total_size, &prng); if (!order) goto err_nodes; - ret = -EINVAL; - drm_mm_init(&mm, 0, 2*total_size - 1); + drm_mm_init(&mm, 0, 2 * total_size - 1); mm.color_adjust = separate_adjacent_colors; for (n = 0; n < total_size; n++) { - if (!expect_insert(&mm, &nodes[n].node, + if (!expect_insert(test, &mm, &nodes[n].node, 1, 0, color++, &insert_modes[0])) { - pr_err("insert failed, step %d\n", n); + KUNIT_FAIL(test, "insert failed, step %d\n", n); goto out; } } @@ -2297,26 +2079,19 @@ static int igt_color_evict(void *ignored) for (mode = evict_modes; mode->name; mode++) { for (n = 1; n <= total_size; n <<= 1) { drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, 0, U64_MAX, - nodes, order, total_size, - n, 1, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u) failed\n", - mode->name, n); + if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size, + n, 1, color++, mode)) { + KUNIT_FAIL(test, "%s evict_color(size=%u) failed\n", mode->name, n); goto out; } } for (n = 1; n < total_size; n <<= 1) { drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, 0, U64_MAX, - nodes, order, total_size, - total_size/2, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed\n", - mode->name, total_size/2, n); + if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size, + total_size / 2, n, color++, mode)) { + KUNIT_FAIL(test, "%s evict_color(size=%u, alignment=%u) failed\n", + mode->name, total_size / 2, n); goto out; } } @@ -2327,13 +2102,10 @@ static int igt_color_evict(void *ignored) DRM_MM_BUG_ON(!nsize); drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, 0, U64_MAX, - nodes, order, total_size, - nsize, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed\n", - mode->name, nsize, n); + if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size, + nsize, n, color++, mode)) { + KUNIT_FAIL(test, "%s evict_color(size=%u, alignment=%u) failed\n", + mode->name, nsize, n); goto out; } } @@ -2341,21 +2113,16 @@ static int igt_color_evict(void *ignored) cond_resched(); } - ret = 0; out: - if (ret) - show_mm(&mm); drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); drm_mm_takedown(&mm); kfree(order); err_nodes: vfree(nodes); -err: - return ret; } -static int igt_color_evict_range(void *ignored) +static void igt_mm_color_evict_range(struct kunit *test) { DRM_RND_STATE(prng, random_seed); const unsigned int total_size = 8192; @@ -2368,29 +2135,25 @@ static int igt_color_evict_range(void *ignored) struct evict_node *nodes; struct drm_mm_node *node, *next; unsigned int *order, n; - int ret, err; /* Like igt_color_evict(), but limited to small portion of the full * drm_mm range. */ - ret = -ENOMEM; nodes = vzalloc(array_size(total_size, sizeof(*nodes))); - if (!nodes) - goto err; + KUNIT_ASSERT_TRUE(test, nodes); order = drm_random_order(total_size, &prng); if (!order) goto err_nodes; - ret = -EINVAL; - drm_mm_init(&mm, 0, 2*total_size - 1); + drm_mm_init(&mm, 0, 2 * total_size - 1); mm.color_adjust = separate_adjacent_colors; for (n = 0; n < total_size; n++) { - if (!expect_insert(&mm, &nodes[n].node, + if (!expect_insert(test, &mm, &nodes[n].node, 1, 0, color++, &insert_modes[0])) { - pr_err("insert failed, step %d\n", n); + KUNIT_FAIL(test, "insert failed, step %d\n", n); goto out; } } @@ -2398,26 +2161,22 @@ static int igt_color_evict_range(void *ignored) for (mode = evict_modes; mode->name; mode++) { for (n = 1; n <= range_size; n <<= 1) { drm_random_reorder(order, range_size, &prng); - err = evict_color(&mm, range_start, range_end, - nodes, order, total_size, - n, 1, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u) failed for range [%x, %x]\n", - mode->name, n, range_start, range_end); + if (evict_color(test, &mm, range_start, range_end, nodes, order, + total_size, n, 1, color++, mode)) { + KUNIT_FAIL(test, + "%s evict_color(size=%u) failed for range [%x, %x]\n", + mode->name, n, range_start, range_end); goto out; } } for (n = 1; n < range_size; n <<= 1) { drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, range_start, range_end, - nodes, order, total_size, - range_size/2, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", - mode->name, total_size/2, n, range_start, range_end); + if (evict_color(test, &mm, range_start, range_end, nodes, order, + total_size, range_size / 2, n, color++, mode)) { + KUNIT_FAIL(test, + "%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", + mode->name, total_size / 2, n, range_start, range_end); goto out; } } @@ -2428,13 +2187,11 @@ static int igt_color_evict_range(void *ignored) DRM_MM_BUG_ON(!nsize); drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, range_start, range_end, - nodes, order, total_size, - nsize, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", - mode->name, nsize, n, range_start, range_end); + if (evict_color(test, &mm, range_start, range_end, nodes, order, + total_size, nsize, n, color++, mode)) { + KUNIT_FAIL(test, + "%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", + mode->name, nsize, n, range_start, range_end); goto out; } } @@ -2442,46 +2199,57 @@ static int igt_color_evict_range(void *ignored) cond_resched(); } - ret = 0; out: - if (ret) - show_mm(&mm); drm_mm_for_each_node_safe(node, next, &mm) drm_mm_remove_node(node); drm_mm_takedown(&mm); kfree(order); err_nodes: vfree(nodes); -err: - return ret; } -#include "drm_selftest.c" - -static int __init test_drm_mm_init(void) +static int drm_mm_init_test(struct kunit *test) { - int err; - while (!random_seed) random_seed = get_random_int(); - pr_info("Testing DRM range manager (struct drm_mm), with random_seed=0x%x max_iterations=%u max_prime=%u\n", - random_seed, max_iterations, max_prime); - err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL); - - return err > 0 ? 0 : err; + return 0; } -static void __exit test_drm_mm_exit(void) -{ -} - -module_init(test_drm_mm_init); -module_exit(test_drm_mm_exit); - module_param(random_seed, uint, 0400); module_param(max_iterations, uint, 0400); module_param(max_prime, uint, 0400); +static struct kunit_case drm_mm_tests[] = { + KUNIT_CASE(igt_mm_init), + KUNIT_CASE(igt_mm_debug), + KUNIT_CASE(igt_mm_reserve), + KUNIT_CASE(igt_mm_insert), + KUNIT_CASE(igt_mm_replace), + KUNIT_CASE(igt_mm_insert_range), + KUNIT_CASE(igt_mm_frag), + KUNIT_CASE(igt_mm_align), + KUNIT_CASE(igt_mm_align32), + KUNIT_CASE(igt_mm_align64), + KUNIT_CASE(igt_mm_evict), + KUNIT_CASE(igt_mm_evict_range), + KUNIT_CASE(igt_mm_topdown), + KUNIT_CASE(igt_mm_bottomup), + KUNIT_CASE(igt_mm_lowest), + KUNIT_CASE(igt_mm_highest), + KUNIT_CASE(igt_mm_color), + KUNIT_CASE(igt_mm_color_evict), + KUNIT_CASE(igt_mm_color_evict_range), + {} +}; + +static struct kunit_suite drm_mm_test_suite = { + .name = "drm_mm", + .init = drm_mm_init_test, + .test_cases = drm_mm_tests, +}; + +kunit_test_suite(drm_mm_test_suite); + MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); From bbd60fee2d2166b2b8722cbad740996ef2e7ce40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Mon, 11 Jul 2022 16:48:01 +0200 Subject: [PATCH 046/396] dma-buf: revert "return only unsignaled fences in dma_fence_unwrap_for_each v3" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8f61973718485f3e89bc4f408f929048b7b47c83. It turned out that this is not correct. Especially the sync_file info IOCTL needs to see even signaled fences to correctly report back their status to userspace. Instead add the filter in the merge function again where it makes sense. Signed-off-by: Christian König <christian.koenig@amd.com> Tested-by: Karolina Drobnik <karolina.drobnik@intel.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220712102849.1562-1-christian.koenig@amd.com --- drivers/dma-buf/dma-fence-unwrap.c | 3 ++- include/linux/dma-fence-unwrap.h | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c index 502a65ea6d44..7002bca792ff 100644 --- a/drivers/dma-buf/dma-fence-unwrap.c +++ b/drivers/dma-buf/dma-fence-unwrap.c @@ -72,7 +72,8 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, count = 0; for (i = 0; i < num_fences; ++i) { dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) - ++count; + if (!dma_fence_is_signaled(tmp)) + ++count; } if (count == 0) diff --git a/include/linux/dma-fence-unwrap.h b/include/linux/dma-fence-unwrap.h index 390de1ee9d35..66b1e56fbb81 100644 --- a/include/linux/dma-fence-unwrap.h +++ b/include/linux/dma-fence-unwrap.h @@ -43,14 +43,10 @@ struct dma_fence *dma_fence_unwrap_next(struct dma_fence_unwrap *cursor); * Unwrap dma_fence_chain and dma_fence_array containers and deep dive into all * potential fences in them. If @head is just a normal fence only that one is * returned. - * - * Note that signalled fences are opportunistically filtered out, which - * means the iteration is potentially over no fence at all. */ #define dma_fence_unwrap_for_each(fence, cursor, head) \ for (fence = dma_fence_unwrap_first(head, cursor); fence; \ - fence = dma_fence_unwrap_next(cursor)) \ - if (!dma_fence_is_signaled(fence)) + fence = dma_fence_unwrap_next(cursor)) struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, struct dma_fence **fences, From 668a8f17b5290d04ef7343636a5588a0692731a1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:31 +0200 Subject: [PATCH 047/396] drm/mipi-dsi: Detach devices when removing the host Whenever the MIPI-DSI host is unregistered, the code of mipi_dsi_host_unregister() loops over every device currently found on that bus and will unregister it. However, it doesn't detach it from the bus first, which leads to all kind of resource leaks if the host wants to perform some clean up whenever a device is detached. Fixes: 068a00233969 ("drm: Add MIPI DSI bus support") Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-2-maxime@cerno.tech --- drivers/gpu/drm/drm_mipi_dsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2e25804d6ffa..3ec02748d56f 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -346,6 +346,7 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv) { struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); + mipi_dsi_detach(dsi); mipi_dsi_device_unregister(dsi); return 0; From 917dd05418148f05d8860b8106da8dcd1d258aaf Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:32 +0200 Subject: [PATCH 048/396] drm/crtc: Introduce drmm_crtc_init_with_planes The DRM-managed function to register a CRTC is drmm_crtc_alloc_with_planes(), which will allocate the underlying structure and initialisation the CRTC. However, we might want to separate the structure creation and the CRTC initialisation, for example if the structure is shared across multiple DRM entities, for example an encoder and a connector. Let's create an helper to only initialise a CRTC that would be passed as an argument. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-3-maxime@cerno.tech --- drivers/gpu/drm/drm_crtc.c | 94 +++++++++++++++++++++++++++++++++----- include/drm/drm_crtc.h | 9 ++++ 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index cad2a7e5166f..df9bf3c9206e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -343,9 +343,10 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc * * The @primary and @cursor planes are only relevant for legacy uAPI, see * &drm_crtc.primary and &drm_crtc.cursor. * - * Note: consider using drmm_crtc_alloc_with_planes() instead of - * drm_crtc_init_with_planes() to let the DRM managed resource infrastructure - * take care of cleanup and deallocation. + * Note: consider using drmm_crtc_alloc_with_planes() or + * drmm_crtc_init_with_planes() instead of drm_crtc_init_with_planes() + * to let the DRM managed resource infrastructure take care of cleanup + * and deallocation. * * Returns: * Zero on success, error code on failure. @@ -370,14 +371,88 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_crtc_init_with_planes); -static void drmm_crtc_alloc_with_planes_cleanup(struct drm_device *dev, - void *ptr) +static void drmm_crtc_init_with_planes_cleanup(struct drm_device *dev, + void *ptr) { struct drm_crtc *crtc = ptr; drm_crtc_cleanup(crtc); } +__printf(6, 0) +static int __drmm_crtc_init_with_planes(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_plane *primary, + struct drm_plane *cursor, + const struct drm_crtc_funcs *funcs, + const char *name, + va_list args) +{ + int ret; + + drm_WARN_ON(dev, funcs && funcs->destroy); + + ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs, + name, args); + if (ret) + return ret; + + ret = drmm_add_action_or_reset(dev, drmm_crtc_init_with_planes_cleanup, + crtc); + if (ret) + return ret; + + return 0; +} + +/** + * drmm_crtc_init_with_planes - Initialise a new CRTC object with + * specified primary and cursor planes. + * @dev: DRM device + * @crtc: CRTC object to init + * @primary: Primary plane for CRTC + * @cursor: Cursor plane for CRTC + * @funcs: callbacks for the new CRTC + * @name: printf style format string for the CRTC name, or NULL for default name + * + * Inits a new object created as base part of a driver crtc object. Drivers + * should use this function instead of drm_crtc_init(), which is only provided + * for backwards compatibility with drivers which do not yet support universal + * planes). For really simple hardware which has only 1 plane look at + * drm_simple_display_pipe_init() instead. + * + * Cleanup is automatically handled through registering + * drmm_crtc_cleanup() with drmm_add_action(). The crtc structure should + * be allocated with drmm_kzalloc(). + * + * The @drm_crtc_funcs.destroy hook must be NULL. + * + * The @primary and @cursor planes are only relevant for legacy uAPI, see + * &drm_crtc.primary and &drm_crtc.cursor. + * + * Returns: + * Zero on success, error code on failure. + */ +int drmm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, + struct drm_plane *primary, + struct drm_plane *cursor, + const struct drm_crtc_funcs *funcs, + const char *name, ...) +{ + va_list ap; + int ret; + + va_start(ap, name); + ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs, + name, ap); + va_end(ap); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drmm_crtc_init_with_planes); + void *__drmm_crtc_alloc_with_planes(struct drm_device *dev, size_t size, size_t offset, struct drm_plane *primary, @@ -400,17 +475,12 @@ void *__drmm_crtc_alloc_with_planes(struct drm_device *dev, crtc = container + offset; va_start(ap, name); - ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs, - name, ap); + ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs, + name, ap); va_end(ap); if (ret) return ERR_PTR(ret); - ret = drmm_add_action_or_reset(dev, drmm_crtc_alloc_with_planes_cleanup, - crtc); - if (ret) - return ERR_PTR(ret); - return container; } EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index ffc1cde331d3..8e1cbc75143e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1216,6 +1216,15 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_plane *cursor, const struct drm_crtc_funcs *funcs, const char *name, ...); + +__printf(6, 7) +int drmm_crtc_init_with_planes(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_plane *primary, + struct drm_plane *cursor, + const struct drm_crtc_funcs *funcs, + const char *name, ...); + void drm_crtc_cleanup(struct drm_crtc *crtc); __printf(7, 8) From f134c9cd9ce829cc66d4d32c57b76de1aab54fe9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:33 +0200 Subject: [PATCH 049/396] drm/encoder: Introduce drmm_encoder_init The DRM-managed function to register an encoder is drmm_encoder_alloc() and its variants, which will allocate the underlying structure and initialisation the encoder. However, we might want to separate the structure creation and the encoder initialisation, for example if the structure is shared across multiple DRM entities, for example an encoder and a connector. Let's create an helper to only initialise an encoder that would be passed as an argument. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-4-maxime@cerno.tech --- drivers/gpu/drm/drm_encoder.c | 75 ++++++++++++++++++++++++++++++----- include/drm/drm_encoder.h | 6 +++ 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c index a940024c8087..1143bc7f3252 100644 --- a/drivers/gpu/drm/drm_encoder.c +++ b/drivers/gpu/drm/drm_encoder.c @@ -27,6 +27,7 @@ #include <drm/drm_drv.h> #include <drm/drm_encoder.h> #include <drm/drm_managed.h> +#include <drm/drm_print.h> #include "drm_crtc_internal.h" @@ -148,9 +149,9 @@ out_put: * the encoder structure. The encoder structure should not be allocated with * devm_kzalloc(). * - * Note: consider using drmm_encoder_alloc() instead of drm_encoder_init() to - * let the DRM managed resource infrastructure take care of cleanup and - * deallocation. + * Note: consider using drmm_encoder_alloc() or drmm_encoder_init() + * instead of drm_encoder_init() to let the DRM managed resource + * infrastructure take care of cleanup and deallocation. * * Returns: * Zero on success, error code on failure. @@ -212,6 +213,30 @@ static void drmm_encoder_alloc_release(struct drm_device *dev, void *ptr) drm_encoder_cleanup(encoder); } +__printf(5, 0) +static int __drmm_encoder_init(struct drm_device *dev, + struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, + int encoder_type, + const char *name, + va_list args) +{ + int ret; + + if (drm_WARN_ON(dev, funcs && funcs->destroy)) + return -EINVAL; + + ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, args); + if (ret) + return ret; + + ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder); + if (ret) + return ret; + + return 0; +} + void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset, const struct drm_encoder_funcs *funcs, int encoder_type, const char *name, ...) @@ -221,9 +246,6 @@ void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset, va_list ap; int ret; - if (WARN_ON(funcs && funcs->destroy)) - return ERR_PTR(-EINVAL); - container = drmm_kzalloc(dev, size, GFP_KERNEL); if (!container) return ERR_PTR(-ENOMEM); @@ -231,19 +253,50 @@ void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset, encoder = container + offset; va_start(ap, name); - ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap); + ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap); va_end(ap); if (ret) return ERR_PTR(ret); - ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder); - if (ret) - return ERR_PTR(ret); - return container; } EXPORT_SYMBOL(__drmm_encoder_alloc); +/** + * drmm_encoder_init - Initialize a preallocated encoder + * @dev: drm device + * @encoder: the encoder to init + * @funcs: callbacks for this encoder (optional) + * @encoder_type: user visible type of the encoder + * @name: printf style format string for the encoder name, or NULL for default name + * + * Initializes a preallocated encoder. Encoder should be subclassed as + * part of driver encoder objects. Cleanup is automatically handled + * through registering drm_encoder_cleanup() with drmm_add_action(). The + * encoder structure should be allocated with drmm_kzalloc(). + * + * The @drm_encoder_funcs.destroy hook must be NULL. + * + * Returns: + * Zero on success, error code on failure. + */ +int drmm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, + int encoder_type, const char *name, ...) +{ + va_list ap; + int ret; + + va_start(ap, name); + ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap); + va_end(ap); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drmm_encoder_init); + static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) { struct drm_connector *connector; diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h index 6e91a0280f31..3a09682af685 100644 --- a/include/drm/drm_encoder.h +++ b/include/drm/drm_encoder.h @@ -194,6 +194,12 @@ int drm_encoder_init(struct drm_device *dev, const struct drm_encoder_funcs *funcs, int encoder_type, const char *name, ...); +__printf(5, 6) +int drmm_encoder_init(struct drm_device *dev, + struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, + int encoder_type, const char *name, ...); + __printf(6, 7) void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset, From d71d8a4b8d10e4e2002d21940a768b389d594637 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:34 +0200 Subject: [PATCH 050/396] drm/connector: Reorder headers Unlike most of the other files in DRM, and Linux in general, the headers in drm_connector.c aren't sorted alphabetically. Let's fix that. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-5-maxime@cerno.tech --- drivers/gpu/drm/drm_connector.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 1ab083b35e3b..d64ee257330e 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -22,15 +22,15 @@ #include <drm/drm_auth.h> #include <drm/drm_connector.h> +#include <drm/drm_drv.h> #include <drm/drm_edid.h> #include <drm/drm_encoder.h> -#include <drm/drm_panel.h> -#include <drm/drm_utils.h> -#include <drm/drm_print.h> -#include <drm/drm_drv.h> #include <drm/drm_file.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_privacy_screen_consumer.h> #include <drm/drm_sysfs.h> +#include <drm/drm_utils.h> #include <linux/fb.h> #include <linux/uaccess.h> From 00ec947c144b374ceb3fe1b4bd2e9ea7454dd630 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:35 +0200 Subject: [PATCH 051/396] drm/connector: Mention the cleanup after drm_connector_init Unlike encoders and CRTCs, the drm_connector_init() and drm_connector_init_with_ddc() don't mention how the cleanup is supposed to be done. Let's add it. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-6-maxime@cerno.tech --- drivers/gpu/drm/drm_connector.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index d64ee257330e..5e98e8651780 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -224,6 +224,10 @@ void drm_connector_free_work_fn(struct work_struct *work) * Initialises a preallocated connector. Connectors should be * subclassed as part of driver connector objects. * + * At driver unload time the driver's &drm_connector_funcs.destroy hook + * should call drm_connector_cleanup() and free the connector structure. + * The connector structure should not be allocated with devm_kzalloc(). + * * Returns: * Zero on success, error code on failure. */ @@ -347,6 +351,10 @@ EXPORT_SYMBOL(drm_connector_init); * Initialises a preallocated connector. Connectors should be * subclassed as part of driver connector objects. * + * At driver unload time the driver's &drm_connector_funcs.destroy hook + * should call drm_connector_cleanup() and free the connector structure. + * The connector structure should not be allocated with devm_kzalloc(). + * * Ensures that the ddc field of the connector is correctly set. * * Returns: From d87fbea50b819b76f180bc8420c5f9efa0670deb Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:36 +0200 Subject: [PATCH 052/396] drm/connector: Clarify when drm_connector_unregister is needed The current documentation for drm_connector_unregister() mentions that it's needed for connectors that have been registered through drm_dev_register(). However, this was a typo and was meant to be drm_connector_register(), which only applies to connectors registered after drm_dev_register() has been called. In addition, it was also mentioning that connectors are unregistered automatically when drm_dev_unregister() is called. This part is a bit misleading, since it might make it appear that drm_connector_unregister() applies either to all connectors, or none of them. After discussing it with Daniel, it appears that we always need to call drm_connector_unregister() on connectors that have been registered with drm_connector_register(), but only those. drm_connector_init() already mentions that it only needs drm_connector_cleanup(), so let's clarify the drm_connector_register() and drm_connector_unregister() documentation to point at each other, and remove the misleading part about drm_dev_unregister(). Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-7-maxime@cerno.tech --- drivers/gpu/drm/drm_connector.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 5e98e8651780..8818fd8fba88 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -525,6 +525,9 @@ EXPORT_SYMBOL(drm_connector_cleanup); * e.g. DP MST connectors. All other connectors will be registered automatically * when calling drm_dev_register(). * + * When the connector is no longer available, callers must call + * drm_connector_unregister(). + * * Returns: * Zero on success, error code on failure. */ @@ -581,9 +584,8 @@ EXPORT_SYMBOL(drm_connector_register); * @connector: the connector to unregister * * Unregister userspace interfaces for a connector. Only call this for - * connectors which have registered explicitly by calling drm_dev_register(), - * since connectors are unregistered automatically when drm_dev_unregister() is - * called. + * connectors which have been registered explicitly by calling + * drm_connector_register(). */ void drm_connector_unregister(struct drm_connector *connector) { From b11af8a25b576cad006411fd904f88199ff9b5ff Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:37 +0200 Subject: [PATCH 053/396] drm/connector: Consolidate Connector Initialization We're going to add a DRM-managed connector initialization function. Since we'll need both the with and without the DDC pointer, having a single function that takes an optional pointer is easier to maintain. Let's create a static function that will back both existing variants, and will be reused by the DRM-managed variant. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Suggested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-8-maxime@cerno.tech --- drivers/gpu/drm/drm_connector.c | 65 +++++++++++++++++---------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 8818fd8fba88..bbdac23bc5c5 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -214,27 +214,11 @@ void drm_connector_free_work_fn(struct work_struct *work) } } -/** - * drm_connector_init - Init a preallocated connector - * @dev: DRM device - * @connector: the connector to init - * @funcs: callbacks for this connector - * @connector_type: user visible type of the connector - * - * Initialises a preallocated connector. Connectors should be - * subclassed as part of driver connector objects. - * - * At driver unload time the driver's &drm_connector_funcs.destroy hook - * should call drm_connector_cleanup() and free the connector structure. - * The connector structure should not be allocated with devm_kzalloc(). - * - * Returns: - * Zero on success, error code on failure. - */ -int drm_connector_init(struct drm_device *dev, - struct drm_connector *connector, - const struct drm_connector_funcs *funcs, - int connector_type) +static int __drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc) { struct drm_mode_config *config = &dev->mode_config; int ret; @@ -282,6 +266,9 @@ int drm_connector_init(struct drm_device *dev, goto out_put_type_id; } + /* provide ddc symlink in sysfs */ + connector->ddc = ddc; + INIT_LIST_HEAD(&connector->global_connector_list_entry); INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); @@ -338,6 +325,31 @@ out_put: return ret; } + +/** + * drm_connector_init - Init a preallocated connector + * @dev: DRM device + * @connector: the connector to init + * @funcs: callbacks for this connector + * @connector_type: user visible type of the connector + * + * Initialises a preallocated connector. Connectors should be + * subclassed as part of driver connector objects. + * + * At driver unload time the driver's &drm_connector_funcs.destroy hook + * should call drm_connector_cleanup() and free the connector structure. + * The connector structure should not be allocated with devm_kzalloc(). + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type) +{ + return __drm_connector_init(dev, connector, funcs, connector_type, NULL); +} EXPORT_SYMBOL(drm_connector_init); /** @@ -366,16 +378,7 @@ int drm_connector_init_with_ddc(struct drm_device *dev, int connector_type, struct i2c_adapter *ddc) { - int ret; - - ret = drm_connector_init(dev, connector, funcs, connector_type); - if (ret) - return ret; - - /* provide ddc symlink in sysfs */ - connector->ddc = ddc; - - return ret; + return __drm_connector_init(dev, connector, funcs, connector_type, ddc); } EXPORT_SYMBOL(drm_connector_init_with_ddc); From a961b197d72601b0363fd7614f9b98d5721f9c6c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:38 +0200 Subject: [PATCH 054/396] drm/connector: Check for destroy implementation Connectors need to be cleaned up with a call to drm_connector_cleanup() in their drm_connector_funcs.destroy implementation. Let's check for this and complain if there's no such function. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-9-maxime@cerno.tech --- drivers/gpu/drm/drm_connector.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index bbdac23bc5c5..dfd170273f5c 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -348,6 +348,9 @@ int drm_connector_init(struct drm_device *dev, const struct drm_connector_funcs *funcs, int connector_type) { + if (drm_WARN_ON(dev, !(funcs && funcs->destroy))) + return -EINVAL; + return __drm_connector_init(dev, connector, funcs, connector_type, NULL); } EXPORT_SYMBOL(drm_connector_init); @@ -378,6 +381,9 @@ int drm_connector_init_with_ddc(struct drm_device *dev, int connector_type, struct i2c_adapter *ddc) { + if (drm_WARN_ON(dev, !(funcs && funcs->destroy))) + return -EINVAL; + return __drm_connector_init(dev, connector, funcs, connector_type, ddc); } EXPORT_SYMBOL(drm_connector_init_with_ddc); From 35a3b82f1bdd60e454de34f984a3f09b38f64b61 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:39 +0200 Subject: [PATCH 055/396] drm/connector: Introduce drmm_connector_init Unlike other DRM entities, there's no helper to create a DRM-managed initialisation of a connector. Let's create an helper to initialise a connector that would be passed as an argument, and handle the cleanup through a DRM-managed action. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-10-maxime@cerno.tech --- drivers/gpu/drm/drm_connector.c | 60 +++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 5 +++ 2 files changed, 65 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index dfd170273f5c..e3142c8142b3 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -26,6 +26,7 @@ #include <drm/drm_edid.h> #include <drm/drm_encoder.h> #include <drm/drm_file.h> +#include <drm/drm_managed.h> #include <drm/drm_panel.h> #include <drm/drm_print.h> #include <drm/drm_privacy_screen_consumer.h> @@ -340,6 +341,10 @@ out_put: * should call drm_connector_cleanup() and free the connector structure. * The connector structure should not be allocated with devm_kzalloc(). * + * Note: consider using drmm_connector_init() instead of + * drm_connector_init() to let the DRM managed resource infrastructure + * take care of cleanup and deallocation. + * * Returns: * Zero on success, error code on failure. */ @@ -372,6 +377,10 @@ EXPORT_SYMBOL(drm_connector_init); * * Ensures that the ddc field of the connector is correctly set. * + * Note: consider using drmm_connector_init() instead of + * drm_connector_init_with_ddc() to let the DRM managed resource + * infrastructure take care of cleanup and deallocation. + * * Returns: * Zero on success, error code on failure. */ @@ -388,6 +397,57 @@ int drm_connector_init_with_ddc(struct drm_device *dev, } EXPORT_SYMBOL(drm_connector_init_with_ddc); +static void drm_connector_cleanup_action(struct drm_device *dev, + void *ptr) +{ + struct drm_connector *connector = ptr; + + drm_connector_cleanup(connector); +} + +/** + * drmm_connector_init - Init a preallocated connector + * @dev: DRM device + * @connector: the connector to init + * @funcs: callbacks for this connector + * @connector_type: user visible type of the connector + * @ddc: optional pointer to the associated ddc adapter + * + * Initialises a preallocated connector. Connectors should be + * subclassed as part of driver connector objects. + * + * Cleanup is automatically handled with a call to + * drm_connector_cleanup() in a DRM-managed action. + * + * The connector structure should be allocated with drmm_kzalloc(). + * + * Returns: + * Zero on success, error code on failure. + */ +int drmm_connector_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc) +{ + int ret; + + if (drm_WARN_ON(dev, funcs && funcs->destroy)) + return -EINVAL; + + ret = __drm_connector_init(dev, connector, funcs, connector_type, NULL); + if (ret) + return ret; + + ret = drmm_add_action_or_reset(dev, drm_connector_cleanup_action, + connector); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drmm_connector_init); + /** * drm_connector_attach_edid_property - attach edid property. * @connector: the connector diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index a1705d6b3fba..2c6fa746efac 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1677,6 +1677,11 @@ int drm_connector_init_with_ddc(struct drm_device *dev, const struct drm_connector_funcs *funcs, int connector_type, struct i2c_adapter *ddc); +int drmm_connector_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc); void drm_connector_attach_edid_property(struct drm_connector *connector); int drm_connector_register(struct drm_connector *connector); void drm_connector_unregister(struct drm_connector *connector); From abea75e9207e7744f524a5373e9c149226e17a5d Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:40 +0200 Subject: [PATCH 056/396] drm/bridge: panel: Introduce drmm_panel_bridge_add Unlike what can be found for other entities, there's no DRM-managed function to create a panel_bridge instance from a panel. Let's introduce one. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-11-maxime@cerno.tech --- drivers/gpu/drm/bridge/panel.c | 39 ++++++++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 2 ++ 2 files changed, 41 insertions(+) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 4277bf4f032b..7d34ebfe611d 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -8,6 +8,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_connector.h> #include <drm/drm_encoder.h> +#include <drm/drm_managed.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> @@ -367,6 +368,44 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, } EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed); +static void drmm_drm_panel_bridge_release(struct drm_device *drm, void *ptr) +{ + struct drm_bridge *bridge = ptr; + + drm_panel_bridge_remove(bridge); +} + +/** + * drmm_panel_bridge_add - Creates a DRM-managed &drm_bridge and + * &drm_connector that just calls the + * appropriate functions from &drm_panel. + * + * @drm: DRM device to tie the bridge lifetime to + * @panel: The drm_panel being wrapped. Must be non-NULL. + * + * This is the DRM-managed version of drm_panel_bridge_add() which + * automatically calls drm_panel_bridge_remove() when @dev is cleaned + * up. + */ +struct drm_bridge *drmm_panel_bridge_add(struct drm_device *drm, + struct drm_panel *panel) +{ + struct drm_bridge *bridge; + int ret; + + bridge = drm_panel_bridge_add_typed(panel, panel->connector_type); + if (IS_ERR(bridge)) + return bridge; + + ret = drmm_add_action_or_reset(drm, drmm_drm_panel_bridge_release, + bridge); + if (ret) + return ERR_PTR(ret); + + return bridge; +} +EXPORT_SYMBOL(drmm_panel_bridge_add); + /** * drm_panel_bridge_connector - return the connector for the panel bridge * @bridge: The drm_bridge. diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index d434ab416ad4..e37a419ac2b4 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -930,6 +930,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev, struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, struct drm_panel *panel, u32 connector_type); +struct drm_bridge *drmm_panel_bridge_add(struct drm_device *drm, + struct drm_panel *panel); struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge); #else static inline bool drm_bridge_is_panel(const struct drm_bridge *bridge) From ae9f1f2ca093906f06311ade42772eeb021af39f Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:41 +0200 Subject: [PATCH 057/396] drm/bridge: panel: Introduce drmm_of_get_bridge Unlike what can be found for other DRM entities, we don't have a DRM-managed function equivalent to devm_drm_of_get_bridge(). Let's create it. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-12-maxime@cerno.tech --- drivers/gpu/drm/bridge/panel.c | 35 ++++++++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 2 ++ 2 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 7d34ebfe611d..216af76d0042 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -459,4 +459,39 @@ struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, return bridge; } EXPORT_SYMBOL(devm_drm_of_get_bridge); + +/** + * drmm_of_get_bridge - Return next bridge in the chain + * @drm: device to tie the bridge lifetime to + * @np: device tree node containing encoder output ports + * @port: port in the device tree node + * @endpoint: endpoint in the device tree node + * + * Given a DT node's port and endpoint number, finds the connected node + * and returns the associated bridge if any, or creates and returns a + * drm panel bridge instance if a panel is connected. + * + * Returns a drmm managed pointer to the bridge if successful, or an error + * pointer otherwise. + */ +struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, + struct device_node *np, + u32 port, u32 endpoint) +{ + struct drm_bridge *bridge; + struct drm_panel *panel; + int ret; + + ret = drm_of_find_panel_or_bridge(np, port, endpoint, + &panel, &bridge); + if (ret) + return ERR_PTR(ret); + + if (panel) + bridge = drmm_panel_bridge_add(drm, panel); + + return bridge; +} +EXPORT_SYMBOL(drmm_of_get_bridge); + #endif diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index e37a419ac2b4..dba5d81e3b4a 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -949,6 +949,8 @@ static inline int drm_panel_bridge_set_orientation(struct drm_connector *connect #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL_BRIDGE) struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct device_node *node, u32 port, u32 endpoint); +struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, struct device_node *node, + u32 port, u32 endpoint); #else static inline struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct device_node *node, From 6cf61bf49c9bdb9ba2d33be812d90dd406326c6c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:42 +0200 Subject: [PATCH 058/396] drm/vc4: drv: Call component_unbind_all() While we were using the component framework to deal with all the DRM subdevices, we were not calling component_unbind_all(). This leads to none of the subdevices freeing up their resources as part of their unbind() or device managed hooks. Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.") Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-13-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.c | 14 ++++++++++++-- drivers/gpu/drm/vc4/vc4_drv.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 292d1b6a01b6..6b8dfa1e7650 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -267,6 +267,13 @@ static void vc4_match_add_drivers(struct device *dev, } } +static void vc4_component_unbind_all(void *ptr) +{ + struct vc4_dev *vc4 = ptr; + + component_unbind_all(vc4->dev, &vc4->base); +} + static const struct of_device_id vc4_dma_range_matches[] = { { .compatible = "brcm,bcm2711-hvs" }, { .compatible = "brcm,bcm2835-hvs" }, @@ -310,6 +317,7 @@ static int vc4_drm_bind(struct device *dev) if (IS_ERR(vc4)) return PTR_ERR(vc4); vc4->is_vc5 = is_vc5; + vc4->dev = dev; drm = &vc4->base; platform_set_drvdata(pdev, drm); @@ -360,6 +368,10 @@ static int vc4_drm_bind(struct device *dev) if (ret) return ret; + ret = devm_add_action_or_reset(dev, vc4_component_unbind_all, vc4); + if (ret) + return ret; + ret = vc4_plane_create_additional_planes(drm); if (ret) goto unbind_all; @@ -380,8 +392,6 @@ static int vc4_drm_bind(struct device *dev) return 0; unbind_all: - component_unbind_all(dev, drm); - return ret; } diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 1beb96b77b8c..950056b83843 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -76,6 +76,7 @@ struct vc4_perfmon { struct vc4_dev { struct drm_device base; + struct device *dev; bool is_vc5; From 4a9551237d44cb051c0a3d7a18d11d6be27ef1d9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:43 +0200 Subject: [PATCH 059/396] drm/vc4: drv: Use drm_dev_unplug When our KMS driver is unbound, the device is no longer there but we might still have users with an opened fd to the KMS device. To avoid any issue in such a situation, every device access needs to be protected by calls to drm_dev_enter() and drm_dev_exit(), and the driver needs to call drm_dev_unplug(). We'll add calls to drm_dev_enter()/drm_dev_exit() in subsequent patches changing the relevant drivers, but let's start by calling drm_dev_unplug(). Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-14-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 6b8dfa1e7650..79a37d18aeb1 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -399,8 +399,7 @@ static void vc4_drm_unbind(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - drm_dev_unregister(drm); - + drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); } From 68e4a69aec4dac161c620665693809b3e69db72f Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:44 +0200 Subject: [PATCH 060/396] drm/vc4: crtc: Create vblank reporting function We'll need that code in the HVS driver, so let's create a shared function to reuse it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-15-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 23 +++++++++++++++-------- drivers/gpu/drm/vc4/vc4_drv.h | 1 + 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 029be98660b3..faad9e564772 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -544,6 +544,20 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) return 0; } +void vc4_crtc_send_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + unsigned long flags; + + if (!crtc->state || !crtc->state->event) + return; + + spin_lock_irqsave(&dev->event_lock, flags); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); +} + static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -567,14 +581,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, * Make sure we issue a vblank event after disabling the CRTC if * someone was waiting it. */ - if (crtc->state->event) { - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); - drm_crtc_send_vblank_event(crtc, crtc->state->event); - crtc->state->event = NULL; - spin_unlock_irqrestore(&dev->event_lock, flags); - } + vc4_crtc_send_vblank(crtc); } static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 950056b83843..de326cf10564 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -862,6 +862,7 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); void vc4_crtc_reset(struct drm_crtc *crtc); void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); +void vc4_crtc_send_vblank(struct drm_crtc *crtc); void vc4_crtc_get_margins(struct drm_crtc_state *state, unsigned int *left, unsigned int *right, unsigned int *top, unsigned int *bottom); From 969cfae1f01d03aee7a87e41d5313e65db4a9c0c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:45 +0200 Subject: [PATCH 061/396] drm/vc4: hvs: Protect device resources after removal Whenever the device and driver are unbound, the main device and all the subdevices will be removed by calling their unbind() method. However, the DRM device itself will only be freed when the last user will have closed it. It means that there is a time window where the device and its resources aren't there anymore, but the userspace can still call into our driver. Fortunately, the DRM framework provides the drm_dev_enter() and drm_dev_exit() functions to make sure our underlying device is still there for the section protected by those calls. Let's add them to the HVS driver. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-16-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hvs.c | 99 ++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index fbaa741dda5f..f2d6e62e7585 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -25,6 +25,7 @@ #include <linux/platform_device.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_vblank.h> #include "vc4_drv.h" @@ -66,11 +67,15 @@ static const struct debugfs_reg32 hvs_regs[] = { void vc4_hvs_dump_state(struct vc4_hvs *hvs) { + struct drm_device *drm = &hvs->vc4->base; struct drm_printer p = drm_info_printer(&hvs->pdev->dev); - int i; + int idx, i; drm_print_regset32(&p, &hvs->regset); + if (!drm_dev_enter(drm, &idx)) + return; + DRM_INFO("HVS ctx:\n"); for (i = 0; i < 64; i += 4) { DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n", @@ -80,6 +85,8 @@ void vc4_hvs_dump_state(struct vc4_hvs *hvs) readl((u32 __iomem *)hvs->dlist + i + 2), readl((u32 __iomem *)hvs->dlist + i + 3)); } + + drm_dev_exit(idx); } static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data) @@ -175,6 +182,11 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs, int ret, i; u32 __iomem *dst_kernel; + /* + * NOTE: We don't need a call to drm_dev_enter()/drm_dev_exit() + * here since that function is only called from vc4_hvs_bind(). + */ + ret = drm_mm_insert_node(&hvs->dlist_mm, space, VC4_KERNEL_DWORDS); if (ret) { DRM_ERROR("Failed to allocate space for filter kernel: %d\n", @@ -199,10 +211,15 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs, static void vc4_hvs_lut_load(struct vc4_hvs *hvs, struct vc4_crtc *vc4_crtc) { + struct drm_device *drm = &hvs->vc4->base; struct drm_crtc *crtc = &vc4_crtc->base; struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); + int idx; u32 i; + if (!drm_dev_enter(drm, &idx)) + return; + /* The LUT memory is laid out with each HVS channel in order, * each of which takes 256 writes for R, 256 for G, then 256 * for B. @@ -217,6 +234,8 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs, HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]); for (i = 0; i < crtc->gamma_size; i++) HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]); + + drm_dev_exit(idx); } static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs, @@ -238,7 +257,12 @@ static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs, u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo) { + struct drm_device *drm = &hvs->vc4->base; u8 field = 0; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return 0; switch (fifo) { case 0: @@ -255,6 +279,7 @@ u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo) break; } + drm_dev_exit(idx); return field; } @@ -267,6 +292,12 @@ int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output) if (!vc4->is_vc5) return output; + /* + * NOTE: We should probably use drm_dev_enter()/drm_dev_exit() + * here, but this function is only used during the DRM device + * initialization, so we should be fine. + */ + switch (output) { case 0: return 0; @@ -315,12 +346,17 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, struct drm_display_mode *mode, bool oneshot) { struct vc4_dev *vc4 = hvs->vc4; + struct drm_device *drm = &vc4->base; struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); unsigned int chan = vc4_crtc_state->assigned_channel; bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; u32 dispbkgndx; u32 dispctrl; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; HVS_WRITE(SCALER_DISPCTRLX(chan), 0); HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET); @@ -362,14 +398,22 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, */ vc4_hvs_lut_load(hvs, vc4_crtc); + drm_dev_exit(idx); + return 0; } void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) { - if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE) + struct drm_device *drm = &hvs->vc4->base; + int idx; + + if (!drm_dev_enter(drm, &idx)) return; + if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE) + goto out; + HVS_WRITE(SCALER_DISPCTRLX(chan), HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET); HVS_WRITE(SCALER_DISPCTRLX(chan), @@ -385,6 +429,9 @@ void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) & (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != SCALER_DISPSTATX_EMPTY); + +out: + drm_dev_exit(idx); } int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) @@ -426,9 +473,15 @@ static void vc4_hvs_install_dlist(struct drm_crtc *crtc) struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_hvs *hvs = vc4->hvs; struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); + int idx; + + if (!drm_dev_enter(dev, &idx)) + return; HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), vc4_state->mm.start); + + drm_dev_exit(idx); } static void vc4_hvs_update_dlist(struct drm_crtc *crtc) @@ -513,6 +566,12 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, bool enable_bg_fill = false; u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start; u32 __iomem *dlist_next = dlist_start; + int idx; + + if (!drm_dev_enter(dev, &idx)) { + vc4_crtc_send_vblank(crtc); + return; + } if (debug_dump_regs) { DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc)); @@ -583,26 +642,44 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc)); vc4_hvs_dump_state(hvs); } + + drm_dev_exit(idx); } void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel) { - u32 dispctrl = HVS_READ(SCALER_DISPCTRL); + struct drm_device *drm = &hvs->vc4->base; + u32 dispctrl; + int idx; + if (!drm_dev_enter(drm, &idx)) + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); dispctrl &= ~SCALER_DISPCTRL_DSPEISLUR(channel); HVS_WRITE(SCALER_DISPCTRL, dispctrl); + + drm_dev_exit(idx); } void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel) { - u32 dispctrl = HVS_READ(SCALER_DISPCTRL); + struct drm_device *drm = &hvs->vc4->base; + u32 dispctrl; + int idx; + if (!drm_dev_enter(drm, &idx)) + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); dispctrl |= SCALER_DISPCTRL_DSPEISLUR(channel); HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_EUFLOW(channel)); HVS_WRITE(SCALER_DISPCTRL, dispctrl); + + drm_dev_exit(idx); } static void vc4_hvs_report_underrun(struct drm_device *dev) @@ -623,6 +700,17 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data) u32 control; u32 status; + /* + * NOTE: We don't need to protect the register access using + * drm_dev_enter() there because the interrupt handler lifetime + * is tied to the device itself, and not to the DRM device. + * + * So when the device will be gone, one of the first thing we + * will be doing will be to unregister the interrupt handler, + * and then unregister the DRM device. drm_dev_enter() would + * thus always succeed if we are here. + */ + status = HVS_READ(SCALER_DISPSTAT); control = HVS_READ(SCALER_DISPCTRL); @@ -655,10 +743,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) u32 dispctrl; u32 reg; - hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL); + hvs = drmm_kzalloc(drm, sizeof(*hvs), GFP_KERNEL); if (!hvs) return -ENOMEM; - hvs->vc4 = vc4; hvs->pdev = pdev; From 398e7ceae6886eaa29babcc0ac8f343e48262716 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:46 +0200 Subject: [PATCH 062/396] drm/vc4: hvs: Remove planes currently allocated before taking down When the HVS driver is unbound, a lot of memory allocations in the LBM and DLIST RAM are still assigned to planes that are still allocated. Thus, we hit a warning when calling drm_mm_takedown() since the memory pool is not completely free of allocations. Let's free all the currently live entries before calling drm_mm_takedown(). Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-17-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hvs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index f2d6e62e7585..a62f222255ce 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -873,11 +873,18 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master, struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_hvs *hvs = vc4->hvs; + struct drm_mm_node *node, *next; if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter)) drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter); + drm_mm_for_each_node_safe(node, next, &vc4->hvs->dlist_mm) + drm_mm_remove_node(node); + drm_mm_takedown(&vc4->hvs->dlist_mm); + + drm_mm_for_each_node_safe(node, next, &vc4->hvs->lbm_mm) + drm_mm_remove_node(node); drm_mm_takedown(&vc4->hvs->lbm_mm); clk_disable_unprepare(hvs->core_clk); From 77c5fb12061f2d8fa28bb0216c9a19a0a6f47ef7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:47 +0200 Subject: [PATCH 063/396] drm/vc4: plane: Take possible_crtcs as an argument vc4_plane_init() currently initialises the plane with no possible CRTCs, and will expect the caller to set it up by itself. Let's change that logic a bit to follow the syntax of drm_universal_plane_init() and pass the possible CRTCs bitmask as an argument to the function instead. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-18-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- drivers/gpu/drm/vc4/vc4_drv.h | 3 ++- drivers/gpu/drm/vc4/vc4_plane.c | 15 +++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index faad9e564772..d391e894ee6c 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1244,7 +1244,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, * requirement of the plane configuration, and reject ones * that will take too much. */ - primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY); + primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0); if (IS_ERR(primary_plane)) { dev_err(drm->dev, "failed to construct primary plane\n"); return PTR_ERR(primary_plane); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index de326cf10564..d935aa3e4409 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -960,7 +960,8 @@ int vc4_kms_load(struct drm_device *dev); /* vc4_plane.c */ struct drm_plane *vc4_plane_init(struct drm_device *dev, - enum drm_plane_type type); + enum drm_plane_type type, + uint32_t possible_crtcs); int vc4_plane_create_additional_planes(struct drm_device *dev); u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); u32 vc4_plane_dlist_size(const struct drm_plane_state *state); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index f27e87a23df7..a344762d86eb 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -1492,7 +1492,8 @@ static const struct drm_plane_funcs vc4_plane_funcs = { }; struct drm_plane *vc4_plane_init(struct drm_device *dev, - enum drm_plane_type type) + enum drm_plane_type type, + uint32_t possible_crtcs) { struct vc4_dev *vc4 = to_vc4_dev(dev); struct drm_plane *plane = NULL; @@ -1523,7 +1524,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, } plane = &vc4_plane->base; - ret = drm_universal_plane_init(dev, plane, 0, + ret = drm_universal_plane_init(dev, plane, possible_crtcs, &vc4_plane_funcs, formats, num_formats, modifiers, type, NULL); @@ -1575,13 +1576,11 @@ int vc4_plane_create_additional_planes(struct drm_device *drm) */ for (i = 0; i < 16; i++) { struct drm_plane *plane = - vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY); + vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, + GENMASK(drm->mode_config.num_crtc - 1, 0)); if (IS_ERR(plane)) continue; - - plane->possible_crtcs = - GENMASK(drm->mode_config.num_crtc - 1, 0); } drm_for_each_crtc(crtc, drm) { @@ -1589,9 +1588,9 @@ int vc4_plane_create_additional_planes(struct drm_device *drm) * since we overlay planes on the CRTC in the order they were * initialized. */ - cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR); + cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR, + drm_crtc_mask(crtc)); if (!IS_ERR(cursor_plane)) { - cursor_plane->possible_crtcs = drm_crtc_mask(crtc); crtc->cursor = cursor_plane; } } From 02792a93103a99abc611e36cdeda9bcfa8924fd2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:48 +0200 Subject: [PATCH 064/396] drm/vc4: crtc: Remove manual plane removal on error When vc4_crtc_bind() fails after vc4_crtc_init() has been called, we have a loop undoing the plane creation and calling destroy on each plane registered and matching the possible_crtcs mask. However, this is redundant with what drm_mode_config_cleanup() is doing, so let's remove it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-19-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index d391e894ee6c..03a799ba9ee8 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1317,7 +1317,7 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) IRQF_SHARED, "vc4 crtc", vc4_crtc); if (ret) - goto err_destroy_planes; + return ret; platform_set_drvdata(pdev, vc4_crtc); @@ -1325,15 +1325,6 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) &vc4_crtc->regset); return 0; - -err_destroy_planes: - list_for_each_entry_safe(destroy_plane, temp, - &drm->mode_config.plane_list, head) { - if (destroy_plane->possible_crtcs == drm_crtc_mask(crtc)) - destroy_plane->funcs->destroy(destroy_plane); - } - - return ret; } static void vc4_crtc_unbind(struct device *dev, struct device *master, From 9872c7a319219346d30a0862424e5495a4e97e0e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:49 +0200 Subject: [PATCH 065/396] drm/vc4: plane: Switch to drmm_universal_plane_alloc() Let's switch to drmm_universal_plane_alloc() for our plane allocation and initialisation to make the driver a bit simpler. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-20-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 1 - drivers/gpu/drm/vc4/vc4_plane.c | 23 ++++++++--------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 03a799ba9ee8..d7cc006b22c9 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1282,7 +1282,6 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) const struct vc4_pv_data *pv_data; struct vc4_crtc *vc4_crtc; struct drm_crtc *crtc; - struct drm_plane *destroy_plane, *temp; int ret; vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index a344762d86eb..82a650268f19 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -1483,8 +1483,6 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, static const struct drm_plane_funcs vc4_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_plane_cleanup, - .set_property = NULL, .reset = vc4_plane_reset, .atomic_duplicate_state = vc4_plane_duplicate_state, .atomic_destroy_state = vc4_plane_destroy_state, @@ -1496,11 +1494,10 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, uint32_t possible_crtcs) { struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_plane *plane = NULL; + struct drm_plane *plane; struct vc4_plane *vc4_plane; u32 formats[ARRAY_SIZE(hvs_formats)]; int num_formats = 0; - int ret = 0; unsigned i; static const uint64_t modifiers[] = { DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, @@ -1511,11 +1508,6 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, DRM_FORMAT_MOD_INVALID }; - vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), - GFP_KERNEL); - if (!vc4_plane) - return ERR_PTR(-ENOMEM); - for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { if (!hvs_formats[i].hvs5_only || vc4->is_vc5) { formats[num_formats] = hvs_formats[i].drm; @@ -1523,13 +1515,14 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, } } + vc4_plane = drmm_universal_plane_alloc(dev, struct vc4_plane, base, + possible_crtcs, + &vc4_plane_funcs, + formats, num_formats, + modifiers, type, NULL); + if (IS_ERR(vc4_plane)) + return ERR_CAST(vc4_plane); plane = &vc4_plane->base; - ret = drm_universal_plane_init(dev, plane, possible_crtcs, - &vc4_plane_funcs, - formats, num_formats, - modifiers, type, NULL); - if (ret) - return ERR_PTR(ret); if (vc4->is_vc5) drm_plane_helper_add(plane, &vc5_plane_helper_funcs); From 6bad4774157c9df64e1b04a8d893e282e16a9c23 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:50 +0200 Subject: [PATCH 066/396] drm/vc4: crtc: Move debugfs_name to crtc_data All the CRTCs, including the TXP, have a debugfs file and name so we can consolidate it into vc4_crtc_data. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-21-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 18 +++++++++--------- drivers/gpu/drm/vc4/vc4_drv.h | 4 ++-- drivers/gpu/drm/vc4/vc4_txp.c | 1 + 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index d7cc006b22c9..bcce61879d53 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1084,10 +1084,10 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { static const struct vc4_pv_data bcm2835_pv0_data = { .base = { + .debugfs_name = "crtc0_regs", .hvs_available_channels = BIT(0), .hvs_output = 0, }, - .debugfs_name = "crtc0_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1098,10 +1098,10 @@ static const struct vc4_pv_data bcm2835_pv0_data = { static const struct vc4_pv_data bcm2835_pv1_data = { .base = { + .debugfs_name = "crtc1_regs", .hvs_available_channels = BIT(2), .hvs_output = 2, }, - .debugfs_name = "crtc1_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1112,10 +1112,10 @@ static const struct vc4_pv_data bcm2835_pv1_data = { static const struct vc4_pv_data bcm2835_pv2_data = { .base = { + .debugfs_name = "crtc2_regs", .hvs_available_channels = BIT(1), .hvs_output = 1, }, - .debugfs_name = "crtc2_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1126,10 +1126,10 @@ static const struct vc4_pv_data bcm2835_pv2_data = { static const struct vc4_pv_data bcm2711_pv0_data = { .base = { + .debugfs_name = "crtc0_regs", .hvs_available_channels = BIT(0), .hvs_output = 0, }, - .debugfs_name = "crtc0_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1140,10 +1140,10 @@ static const struct vc4_pv_data bcm2711_pv0_data = { static const struct vc4_pv_data bcm2711_pv1_data = { .base = { + .debugfs_name = "crtc1_regs", .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), .hvs_output = 3, }, - .debugfs_name = "crtc1_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1154,10 +1154,10 @@ static const struct vc4_pv_data bcm2711_pv1_data = { static const struct vc4_pv_data bcm2711_pv2_data = { .base = { + .debugfs_name = "crtc2_regs", .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), .hvs_output = 4, }, - .debugfs_name = "crtc2_regs", .fifo_depth = 256, .pixels_per_clock = 2, .encoder_types = { @@ -1167,10 +1167,10 @@ static const struct vc4_pv_data bcm2711_pv2_data = { static const struct vc4_pv_data bcm2711_pv3_data = { .base = { + .debugfs_name = "crtc3_regs", .hvs_available_channels = BIT(1), .hvs_output = 1, }, - .debugfs_name = "crtc3_regs", .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { @@ -1180,10 +1180,10 @@ static const struct vc4_pv_data bcm2711_pv3_data = { static const struct vc4_pv_data bcm2711_pv4_data = { .base = { + .debugfs_name = "crtc4_regs", .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), .hvs_output = 5, }, - .debugfs_name = "crtc4_regs", .fifo_depth = 64, .pixels_per_clock = 2, .encoder_types = { @@ -1320,7 +1320,7 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) platform_set_drvdata(pdev, vc4_crtc); - vc4_debugfs_add_regset32(drm, pv_data->debugfs_name, + vc4_debugfs_add_regset32(drm, pv_data->base.debugfs_name, &vc4_crtc->regset); return 0; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index d935aa3e4409..443894e1715d 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -459,6 +459,8 @@ to_vc4_encoder(struct drm_encoder *encoder) } struct vc4_crtc_data { + const char *debugfs_name; + /* Bitmask of channels (FIFOs) of the HVS that the output can source from */ unsigned int hvs_available_channels; @@ -476,8 +478,6 @@ struct vc4_pv_data { u8 pixels_per_clock; enum vc4_encoder_type encoder_types[4]; - const char *debugfs_name; - }; struct vc4_crtc { diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index d20b0bc51a18..20e08e31aa1b 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -461,6 +461,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data) } static const struct vc4_crtc_data vc4_txp_crtc_data = { + .debugfs_name = "txp_regs", .hvs_available_channels = BIT(2), .hvs_output = 2, }; From 7cc4214c27cf8d664358db402a179bf6ab2db862 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:51 +0200 Subject: [PATCH 067/396] drm/vc4: crtc: Switch to drmm_kzalloc Our internal structure that stores the DRM entities structure is allocated through a device-managed kzalloc. This means that this will eventually be freed whenever the device is removed. In our case, the most likely source of removal is that the main device is going to be unbound, and component_unbind_all() is being run. However, it occurs while the DRM device is still registered, which will create dangling pointers, eventually resulting in use-after-free. Switch to a DRM-managed allocation to keep our structure until the DRM driver doesn't need it anymore. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-22-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index bcce61879d53..d5158a6c0f21 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1284,7 +1284,7 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) struct drm_crtc *crtc; int ret; - vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL); + vc4_crtc = drmm_kzalloc(drm, sizeof(*vc4_crtc), GFP_KERNEL); if (!vc4_crtc) return -ENOMEM; crtc = &vc4_crtc->base; From 77ef4c1702fb370da126ff39b94e80a74ce9f095 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:52 +0200 Subject: [PATCH 068/396] drm/vc4: crtc: Switch to DRM-managed CRTC initialization The current code will call drm_crtc_cleanup() when the device is unbound. However, by then, there might still be some references held to that CRTC, including by the userspace that might still have the DRM device open. Let's switch to a DRM-managed initialization to clean up after ourselves only once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-23-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 16 ++++++---------- drivers/gpu/drm/vc4/vc4_drv.h | 1 - drivers/gpu/drm/vc4/vc4_txp.c | 1 - 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index d5158a6c0f21..3768a2a57ca9 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -206,11 +206,6 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, return ret; } -void vc4_crtc_destroy(struct drm_crtc *crtc) -{ - drm_crtc_cleanup(crtc); -} - static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) { const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); @@ -1059,7 +1054,6 @@ void vc4_crtc_reset(struct drm_crtc *crtc) static const struct drm_crtc_funcs vc4_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = vc4_crtc_destroy, .page_flip = vc4_page_flip, .set_property = NULL, .cursor_set = NULL, /* handled by drm_mode_cursor_universal */ @@ -1237,6 +1231,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, struct drm_crtc *crtc = &vc4_crtc->base; struct drm_plane *primary_plane; unsigned int i; + int ret; /* For now, we create just the primary and the legacy cursor * planes. We should be able to stack more planes on easily, @@ -1251,8 +1246,11 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, } spin_lock_init(&vc4_crtc->irq_lock); - drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, - crtc_funcs, NULL); + ret = drmm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, + crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(crtc, crtc_helper_funcs); if (!vc4->is_vc5) { @@ -1332,8 +1330,6 @@ static void vc4_crtc_unbind(struct device *dev, struct device *master, struct platform_device *pdev = to_platform_device(dev); struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev); - vc4_crtc_destroy(&vc4_crtc->base); - CRTC_WRITE(PV_INTEN, 0); platform_set_drvdata(pdev, NULL); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 443894e1715d..116e54fc1363 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -851,7 +851,6 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc); int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, const struct drm_crtc_funcs *crtc_funcs, const struct drm_crtc_helper_funcs *crtc_helper_funcs); -void vc4_crtc_destroy(struct drm_crtc *crtc); int vc4_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 20e08e31aa1b..448d48e7e99f 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -384,7 +384,6 @@ static void vc4_txp_disable_vblank(struct drm_crtc *crtc) {} static const struct drm_crtc_funcs vc4_txp_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = vc4_crtc_destroy, .page_flip = vc4_page_flip, .reset = vc4_crtc_reset, .atomic_duplicate_state = vc4_crtc_duplicate_state, From 693e35dcde748387c6dc538de6c3d78b3d2da866 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:53 +0200 Subject: [PATCH 069/396] drm/vc4: dpi: Remove vc4_dev dpi pointer There's no user for that pointer so let's just get rid of it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-24-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 7 ------- drivers/gpu/drm/vc4/vc4_drv.h | 1 - 2 files changed, 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index ef5e3921062c..d3625dcb5dcb 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -269,7 +269,6 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_dpi *dpi; struct vc4_dpi_encoder *vc4_dpi_encoder; int ret; @@ -328,8 +327,6 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, dpi); - vc4->dpi = dpi; - vc4_debugfs_add_regset32(drm, "dpi_regs", &dpi->regset); return 0; @@ -343,8 +340,6 @@ err_destroy_encoder: static void vc4_dpi_unbind(struct device *dev, struct device *master, void *data) { - struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_dpi *dpi = dev_get_drvdata(dev); drm_of_panel_bridge_remove(dev->of_node, 0, 0); @@ -352,8 +347,6 @@ static void vc4_dpi_unbind(struct device *dev, struct device *master, drm_encoder_cleanup(dpi->encoder); clk_disable_unprepare(dpi->core_clock); - - vc4->dpi = NULL; } static const struct component_ops vc4_dpi_ops = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 116e54fc1363..835d286c2802 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -84,7 +84,6 @@ struct vc4_dev { struct vc4_hvs *hvs; struct vc4_v3d *v3d; - struct vc4_dpi *dpi; struct vc4_vec *vec; struct vc4_txp *txp; From 7c9a4bab7aeb4be917d4202a99a780b40eaa78c7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:54 +0200 Subject: [PATCH 070/396] drm/vc4: dpi: Embed DRM structures into the private structure The VC4 DPI driver private structure contains only a pointer to the encoder it implements. This makes the overall structure somewhat inconsistent with the rest of the driver, and complicates its initialisation without any apparent gain. Let's embed the drm_encoder structure (through the vc4_encoder one) into struct vc4_dpi to fix both issues. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-25-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 49 ++++++++++++----------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index d3625dcb5dcb..7c4bfbd7ed9f 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -84,9 +84,9 @@ /* General DPI hardware state. */ struct vc4_dpi { - struct platform_device *pdev; + struct vc4_encoder encoder; - struct drm_encoder *encoder; + struct platform_device *pdev; void __iomem *regs; @@ -96,21 +96,15 @@ struct vc4_dpi { struct debugfs_regset32 regset; }; +static inline struct vc4_dpi * +to_vc4_dpi(struct drm_encoder *encoder) +{ + return container_of(encoder, struct vc4_dpi, encoder.base); +} + #define DPI_READ(offset) readl(dpi->regs + (offset)) #define DPI_WRITE(offset, val) writel(val, dpi->regs + (offset)) -/* VC4 DPI encoder KMS struct */ -struct vc4_dpi_encoder { - struct vc4_encoder base; - struct vc4_dpi *dpi; -}; - -static inline struct vc4_dpi_encoder * -to_vc4_dpi_encoder(struct drm_encoder *encoder) -{ - return container_of(encoder, struct vc4_dpi_encoder, base.base); -} - static const struct debugfs_reg32 dpi_regs[] = { VC4_REG32(DPI_C), VC4_REG32(DPI_ID), @@ -118,8 +112,7 @@ static const struct debugfs_reg32 dpi_regs[] = { static void vc4_dpi_encoder_disable(struct drm_encoder *encoder) { - struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder); - struct vc4_dpi *dpi = vc4_encoder->dpi; + struct vc4_dpi *dpi = to_vc4_dpi(encoder); clk_disable_unprepare(dpi->pixel_clock); } @@ -128,8 +121,7 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct drm_display_mode *mode = &encoder->crtc->mode; - struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder); - struct vc4_dpi *dpi = vc4_encoder->dpi; + struct vc4_dpi *dpi = to_vc4_dpi(encoder); struct drm_connector_list_iter conn_iter; struct drm_connector *connector = NULL, *connector_scan; u32 dpi_c = DPI_ENABLE; @@ -262,7 +254,7 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi) return PTR_ERR(bridge); } - return drm_bridge_attach(dpi->encoder, bridge, NULL, 0); + return drm_bridge_attach(&dpi->encoder.base, bridge, NULL, 0); } static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) @@ -270,21 +262,12 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); struct vc4_dpi *dpi; - struct vc4_dpi_encoder *vc4_dpi_encoder; int ret; dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); if (!dpi) return -ENOMEM; - - vc4_dpi_encoder = devm_kzalloc(dev, sizeof(*vc4_dpi_encoder), - GFP_KERNEL); - if (!vc4_dpi_encoder) - return -ENOMEM; - vc4_dpi_encoder->base.type = VC4_ENCODER_TYPE_DPI; - vc4_dpi_encoder->dpi = dpi; - dpi->encoder = &vc4_dpi_encoder->base.base; - + dpi->encoder.type = VC4_ENCODER_TYPE_DPI; dpi->pdev = pdev; dpi->regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(dpi->regs)) @@ -318,8 +301,8 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) if (ret) DRM_ERROR("Failed to turn on core clock: %d\n", ret); - drm_simple_encoder_init(drm, dpi->encoder, DRM_MODE_ENCODER_DPI); - drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs); + drm_simple_encoder_init(drm, &dpi->encoder.base, DRM_MODE_ENCODER_DPI); + drm_encoder_helper_add(&dpi->encoder.base, &vc4_dpi_encoder_helper_funcs); ret = vc4_dpi_init_bridge(dpi); if (ret) @@ -332,7 +315,7 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) return 0; err_destroy_encoder: - drm_encoder_cleanup(dpi->encoder); + drm_encoder_cleanup(&dpi->encoder.base); clk_disable_unprepare(dpi->core_clock); return ret; } @@ -344,7 +327,7 @@ static void vc4_dpi_unbind(struct device *dev, struct device *master, drm_of_panel_bridge_remove(dev->of_node, 0, 0); - drm_encoder_cleanup(dpi->encoder); + drm_encoder_cleanup(&dpi->encoder.base); clk_disable_unprepare(dpi->core_clock); } From 7f0ba8f98a4ec3bee6a5d612e676a75791c0f127 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:55 +0200 Subject: [PATCH 071/396] drm/vc4: dpi: Switch to drmm_kzalloc Our internal structure that stores the DRM entities structure is allocated through a device-managed kzalloc. This means that this will eventually be freed whenever the device is removed. In our case, the most likely source of removal is that the main device is going to be unbound, and component_unbind_all() is being run. However, it occurs while the DRM device is still registered, which will create dangling pointers, eventually resulting in use-after-free. Switch to a DRM-managed allocation to keep our structure until the DRM driver doesn't need it anymore. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-26-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 7c4bfbd7ed9f..7a1112c12be4 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -264,9 +264,10 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) struct vc4_dpi *dpi; int ret; - dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); + dpi = drmm_kzalloc(drm, sizeof(*dpi), GFP_KERNEL); if (!dpi) return -ENOMEM; + dpi->encoder.type = VC4_ENCODER_TYPE_DPI; dpi->pdev = pdev; dpi->regs = vc4_ioremap_regs(pdev, 0); From ff5b18ce8a5b4fccabd46ed7f17ef3e7f2d1f8e0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:56 +0200 Subject: [PATCH 072/396] drm/vc4: dpi: Return an error if we can't enable our clock If we fail to enable the DPI clock, we just ignore the error and moves forward. Let's return an error instead. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-27-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 7a1112c12be4..7028a789919d 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -290,6 +290,7 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) DRM_ERROR("Failed to get core clock: %d\n", ret); return ret; } + dpi->pixel_clock = devm_clk_get(dev, "pixel"); if (IS_ERR(dpi->pixel_clock)) { ret = PTR_ERR(dpi->pixel_clock); @@ -299,8 +300,10 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) } ret = clk_prepare_enable(dpi->core_clock); - if (ret) + if (ret) { DRM_ERROR("Failed to turn on core clock: %d\n", ret); + return ret; + } drm_simple_encoder_init(drm, &dpi->encoder.base, DRM_MODE_ENCODER_DPI); drm_encoder_helper_add(&dpi->encoder.base, &vc4_dpi_encoder_helper_funcs); From 5801eda938f5f98cbdb6bc83e2c35499735f006a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:57 +0200 Subject: [PATCH 073/396] drm/vc4: dpi: Remove unnecessary drm_of_panel_bridge_remove call Since we have a managed call to create our panel_bridge instance, the call to drm_of_panel_bridge_remove() at unbind is both redundant and dangerous since it might lead to a use-after-free. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-28-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 7028a789919d..f18b05cee8bc 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -329,8 +329,6 @@ static void vc4_dpi_unbind(struct device *dev, struct device *master, { struct vc4_dpi *dpi = dev_get_drvdata(dev); - drm_of_panel_bridge_remove(dev->of_node, 0, 0); - drm_encoder_cleanup(&dpi->encoder.base); clk_disable_unprepare(dpi->core_clock); From 77932adf2a2c9625da8bc8885b626690ee500601 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:58 +0200 Subject: [PATCH 074/396] drm/vc4: dpi: Add action to disable the clock The DPI controller has two clocks called core and pixel, the core clock being enabled at bind time. Adding a device-managed action will make the error path easier, so let's create one to disable it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-29-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index f18b05cee8bc..c4ea99f85e5b 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -257,6 +257,13 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi) return drm_bridge_attach(&dpi->encoder.base, bridge, NULL, 0); } +static void vc4_dpi_disable_clock(void *ptr) +{ + struct vc4_dpi *dpi = ptr; + + clk_disable_unprepare(dpi->core_clock); +} + static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -305,6 +312,10 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) return ret; } + ret = devm_add_action_or_reset(dev, vc4_dpi_disable_clock, dpi); + if (ret) + return ret; + drm_simple_encoder_init(drm, &dpi->encoder.base, DRM_MODE_ENCODER_DPI); drm_encoder_helper_add(&dpi->encoder.base, &vc4_dpi_encoder_helper_funcs); @@ -320,7 +331,6 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) err_destroy_encoder: drm_encoder_cleanup(&dpi->encoder.base); - clk_disable_unprepare(dpi->core_clock); return ret; } @@ -330,8 +340,6 @@ static void vc4_dpi_unbind(struct device *dev, struct device *master, struct vc4_dpi *dpi = dev_get_drvdata(dev); drm_encoder_cleanup(&dpi->encoder.base); - - clk_disable_unprepare(dpi->core_clock); } static const struct component_ops vc4_dpi_ops = { From e126d318002639c979f23764f5d496a78e9bd85e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:38:59 +0200 Subject: [PATCH 075/396] drm/vc4: dpi: Switch to DRM-managed encoder initialization The current code will call drm_encoder_cleanup() when the device is unbound. However, by then, there might still be some references held to that encoder, including by the userspace that might still have the DRM device open. Let's switch to a DRM-managed initialization to clean up after ourselves only once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-30-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index c4ea99f85e5b..ceb14aea6c05 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -316,35 +316,28 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; - drm_simple_encoder_init(drm, &dpi->encoder.base, DRM_MODE_ENCODER_DPI); + ret = drmm_encoder_init(drm, &dpi->encoder.base, + NULL, + DRM_MODE_ENCODER_DPI, + NULL); + if (ret) + return ret; + drm_encoder_helper_add(&dpi->encoder.base, &vc4_dpi_encoder_helper_funcs); ret = vc4_dpi_init_bridge(dpi); if (ret) - goto err_destroy_encoder; + return ret; dev_set_drvdata(dev, dpi); vc4_debugfs_add_regset32(drm, "dpi_regs", &dpi->regset); return 0; - -err_destroy_encoder: - drm_encoder_cleanup(&dpi->encoder.base); - return ret; -} - -static void vc4_dpi_unbind(struct device *dev, struct device *master, - void *data) -{ - struct vc4_dpi *dpi = dev_get_drvdata(dev); - - drm_encoder_cleanup(&dpi->encoder.base); } static const struct component_ops vc4_dpi_ops = { .bind = vc4_dpi_bind, - .unbind = vc4_dpi_unbind, }; static int vc4_dpi_dev_probe(struct platform_device *pdev) From 055af0235aef8110a1c44f5fc04c5c206e9e58fb Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:00 +0200 Subject: [PATCH 076/396] drm/vc4: dpi: Switch to drmm_of_get_bridge The current code uses a device-managed function to retrieve the next bridge downstream. However, that means that it will be removed at unbind time, where the DRM device is still very much live and might still have some applications that still have it open. Switch to a DRM-managed variant to clean everything up once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-31-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index ceb14aea6c05..660feea0534d 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -240,10 +240,11 @@ static const struct of_device_id vc4_dpi_dt_match[] = { */ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi) { + struct drm_device *drm = dpi->encoder.base.dev; struct device *dev = &dpi->pdev->dev; struct drm_bridge *bridge; - bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); + bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0); if (IS_ERR(bridge)) { /* If nothing was connected in the DT, that's not an * error. From 71b1bd4c2bd404b28cc499fa37d02e32f55de865 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:01 +0200 Subject: [PATCH 077/396] drm/vc4: dpi: Protect device resources Our current code now mixes some resources whose lifetime are tied to the device (clocks, IO mappings, etc.) and some that are tied to the DRM device (encoder, bridge). The device one will be freed at unbind time, but the DRM one will only be freed when the last user of the DRM device closes its file handle. So we end up with a time window during which we can call the encoder hooks, but we don't have access to the underlying resources and device. Let's protect all those sections with drm_dev_enter() and drm_dev_exit() so that we bail out if we are during that window. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-32-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dpi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 660feea0534d..7286a3333538 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -13,6 +13,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> +#include <drm/drm_drv.h> #include <drm/drm_edid.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> @@ -112,9 +113,16 @@ static const struct debugfs_reg32 dpi_regs[] = { static void vc4_dpi_encoder_disable(struct drm_encoder *encoder) { + struct drm_device *dev = encoder->dev; struct vc4_dpi *dpi = to_vc4_dpi(encoder); + int idx; + + if (!drm_dev_enter(dev, &idx)) + return; clk_disable_unprepare(dpi->pixel_clock); + + drm_dev_exit(idx); } static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) @@ -125,6 +133,7 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) struct drm_connector_list_iter conn_iter; struct drm_connector *connector = NULL, *connector_scan; u32 dpi_c = DPI_ENABLE; + int idx; int ret; /* Look up the connector attached to DPI so we can get the @@ -204,6 +213,9 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) dpi_c |= DPI_VSYNC_DISABLE; } + if (!drm_dev_enter(dev, &idx)) + return; + DPI_WRITE(DPI_C, dpi_c); ret = clk_set_rate(dpi->pixel_clock, mode->clock * 1000); @@ -213,6 +225,8 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) ret = clk_prepare_enable(dpi->pixel_clock); if (ret) DRM_ERROR("Failed to set clock rate: %d\n", ret); + + drm_dev_exit(idx); } static enum drm_mode_status vc4_dpi_encoder_mode_valid(struct drm_encoder *encoder, From 73b68b28a9e819e600ca2d0640721ae61bdaf55a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:02 +0200 Subject: [PATCH 078/396] drm/vc4: dsi: Embed DRM structures into the private structure The VC4 DSI driver private structure contains only a pointer to the encoder it implements. This makes the overall structure somewhat inconsistent with the rest of the driver, and complicates its initialisation without any apparent gain. Let's embed the drm_encoder structure (through the vc4_encoder one) into struct vc4_dsi to fix both issues. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-33-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dsi.c | 58 +++++++++++++---------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index b7b2c76770dc..72889524540e 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -549,10 +549,11 @@ struct vc4_dsi_variant { /* General DSI hardware state. */ struct vc4_dsi { + struct vc4_encoder encoder; + struct mipi_dsi_host dsi_host; + struct platform_device *pdev; - struct mipi_dsi_host dsi_host; - struct drm_encoder *encoder; struct drm_bridge *bridge; struct list_head bridge_chain; @@ -600,6 +601,12 @@ struct vc4_dsi { #define host_to_dsi(host) container_of(host, struct vc4_dsi, dsi_host) +static inline struct vc4_dsi * +to_vc4_dsi(struct drm_encoder *encoder) +{ + return container_of(encoder, struct vc4_dsi, encoder.base); +} + static inline void dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val) { @@ -644,18 +651,6 @@ dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val) DSI_WRITE(dsi->variant->port ? DSI1_##offset : DSI0_##offset, val) #define DSI_PORT_BIT(bit) (dsi->variant->port ? DSI1_##bit : DSI0_##bit) -/* VC4 DSI encoder KMS struct */ -struct vc4_dsi_encoder { - struct vc4_encoder base; - struct vc4_dsi *dsi; -}; - -static inline struct vc4_dsi_encoder * -to_vc4_dsi_encoder(struct drm_encoder *encoder) -{ - return container_of(encoder, struct vc4_dsi_encoder, base.base); -} - static const struct debugfs_reg32 dsi0_regs[] = { VC4_REG32(DSI0_CTRL), VC4_REG32(DSI0_STAT), @@ -795,8 +790,7 @@ dsi_esc_timing(u32 ns) static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) { - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder); - struct vc4_dsi *dsi = vc4_encoder->dsi; + struct vc4_dsi *dsi = to_vc4_dsi(encoder); struct device *dev = &dsi->pdev->dev; struct drm_bridge *iter; @@ -839,8 +833,7 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder); - struct vc4_dsi *dsi = vc4_encoder->dsi; + struct vc4_dsi *dsi = to_vc4_dsi(encoder); struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock); unsigned long parent_rate = clk_get_rate(phy_parent); unsigned long pixel_clock_hz = mode->clock * 1000; @@ -875,8 +868,7 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder, static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder); - struct vc4_dsi *dsi = vc4_encoder->dsi; + struct vc4_dsi *dsi = to_vc4_dsi(encoder); struct device *dev = &dsi->pdev->dev; bool debug_dump_regs = false; struct drm_bridge *iter; @@ -1569,21 +1561,14 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); struct vc4_dsi *dsi = dev_get_drvdata(dev); - struct vc4_dsi_encoder *vc4_dsi_encoder; + struct drm_encoder *encoder = &dsi->encoder.base; int ret; dsi->variant = of_device_get_match_data(dev); - vc4_dsi_encoder = devm_kzalloc(dev, sizeof(*vc4_dsi_encoder), - GFP_KERNEL); - if (!vc4_dsi_encoder) - return -ENOMEM; - INIT_LIST_HEAD(&dsi->bridge_chain); - vc4_dsi_encoder->base.type = dsi->variant->port ? - VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0; - vc4_dsi_encoder->dsi = dsi; - dsi->encoder = &vc4_dsi_encoder->base.base; + dsi->encoder.type = dsi->variant->port ? + VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0; dsi->regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(dsi->regs)) @@ -1702,10 +1687,10 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; - drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI); - drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); + drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_DSI); + drm_encoder_helper_add(encoder, &vc4_dsi_encoder_helper_funcs); - ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0); + ret = drm_bridge_attach(encoder, dsi->bridge, NULL, 0); if (ret) return ret; /* Disable the atomic helper calls into the bridge. We @@ -1713,7 +1698,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) * from our driver, since we need to sequence them within the * encoder's enable/disable paths. */ - list_splice_init(&dsi->encoder->bridge_chain, &dsi->bridge_chain); + list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); vc4_debugfs_add_regset32(drm, dsi->variant->debugfs_name, &dsi->regset); @@ -1726,6 +1711,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, void *data) { struct vc4_dsi *dsi = dev_get_drvdata(dev); + struct drm_encoder *encoder = &dsi->encoder.base; pm_runtime_disable(dev); @@ -1733,8 +1719,8 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, * Restore the bridge_chain so the bridge detach procedure can happen * normally. */ - list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain); - drm_encoder_cleanup(dsi->encoder); + list_splice_init(&dsi->bridge_chain, &encoder->bridge_chain); + drm_encoder_cleanup(encoder); } static const struct component_ops vc4_dsi_ops = { From 6f0ca506c30e2b2c8d3b86fe33989c5257aaa34b Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:03 +0200 Subject: [PATCH 079/396] drm/vc4: dsi: Switch to DRM-managed encoder initialization The current code will call drm_encoder_cleanup() when the device is unbound. However, by then, there might still be some references held to that encoder, including by the userspace that might still have the DRM device open. Let's switch to a DRM-managed initialization to clean up after ourselves only once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-34-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dsi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 72889524540e..1a55b7ea52a8 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1687,7 +1687,13 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; - drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_DSI); + ret = drmm_encoder_init(drm, encoder, + NULL, + DRM_MODE_ENCODER_DSI, + NULL); + if (ret) + return ret; + drm_encoder_helper_add(encoder, &vc4_dsi_encoder_helper_funcs); ret = drm_bridge_attach(encoder, dsi->bridge, NULL, 0); @@ -1720,7 +1726,6 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, * normally. */ list_splice_init(&dsi->bridge_chain, &encoder->bridge_chain); - drm_encoder_cleanup(encoder); } static const struct component_ops vc4_dsi_ops = { From 2a87d48c3342ede66b15649bcbbaf999ccc9a83a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:04 +0200 Subject: [PATCH 080/396] drm/vc4: dsi: Switch to drmm_of_get_bridge The current code uses a device-managed function to retrieve the next bridge downstream. However, that means that it will be removed at unbind time, where the DRM device is still very much live and might still have some applications that still have it open. Switch to a DRM-managed variant to clean everything up once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-35-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 1a55b7ea52a8..13266ff334d0 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1672,7 +1672,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) return ret; } - dsi->bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); + dsi->bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0); if (IS_ERR(dsi->bridge)) return PTR_ERR(dsi->bridge); From 6eda15642989e32ff5e70281cabf7b596fe4f280 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:05 +0200 Subject: [PATCH 081/396] drm/vc4: dsi: Fix the driver structure lifetime The vc4_dsi structure is currently allocated through a device-managed allocation. This can lead to use-after-free issues however in the unbinding path since the DRM entities will stick around, but the underlying structure has been freed. However, we can't just fix it by using a DRM-managed allocation like we did for the other drivers since the DSI case is a bit more intricate. Indeed, the structure will be allocated at probe time, when we don't have a DRM device yet, to be able to register the DSI bus driver. We will then reuse it at bind time to register our KMS entities in the framework. In order to work around both constraints, we can use a kref to track the users of the structure (DSI host, and KMS), and then put our structure when the DSI host will have been unregistered, and through a DRM-managed action that will execute once we won't need the KMS entities anymore. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-36-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dsi.c | 38 ++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 13266ff334d0..4f5bdb9a328b 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -552,6 +552,8 @@ struct vc4_dsi { struct vc4_encoder encoder; struct mipi_dsi_host dsi_host; + struct kref kref; + struct platform_device *pdev; struct drm_bridge *bridge; @@ -1556,6 +1558,31 @@ static void vc4_dsi_dma_chan_release(void *ptr) dsi->reg_dma_chan = NULL; } +static void vc4_dsi_release(struct kref *kref) +{ + struct vc4_dsi *dsi = + container_of(kref, struct vc4_dsi, kref); + + kfree(dsi); +} + +static void vc4_dsi_get(struct vc4_dsi *dsi) +{ + kref_get(&dsi->kref); +} + +static void vc4_dsi_put(struct vc4_dsi *dsi) +{ + kref_put(&dsi->kref, &vc4_dsi_release); +} + +static void vc4_dsi_release_action(struct drm_device *drm, void *ptr) +{ + struct vc4_dsi *dsi = ptr; + + vc4_dsi_put(dsi); +} + static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -1564,6 +1591,12 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) struct drm_encoder *encoder = &dsi->encoder.base; int ret; + vc4_dsi_get(dsi); + + ret = drmm_add_action_or_reset(drm, vc4_dsi_release_action, dsi); + if (ret) + return ret; + dsi->variant = of_device_get_match_data(dev); INIT_LIST_HEAD(&dsi->bridge_chain); @@ -1738,11 +1771,12 @@ static int vc4_dsi_dev_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct vc4_dsi *dsi; - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); + dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); if (!dsi) return -ENOMEM; dev_set_drvdata(dev, dsi); + kref_init(&dsi->kref); dsi->pdev = pdev; dsi->dsi_host.ops = &vc4_dsi_host_ops; dsi->dsi_host.dev = dev; @@ -1757,6 +1791,8 @@ static int vc4_dsi_dev_remove(struct platform_device *pdev) struct vc4_dsi *dsi = dev_get_drvdata(dev); mipi_dsi_host_unregister(&dsi->dsi_host); + vc4_dsi_put(dsi); + return 0; } From 7b44e4de72dcd5a5769ad19c5cc2cc2b28c0a778 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:06 +0200 Subject: [PATCH 082/396] drm/vc4: dsi: Switch to devm_pm_runtime_enable devm_pm_runtime_enable() simplifies the driver a bit since it will call pm_runtime_disable() automatically through a device-managed action. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-37-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_dsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 4f5bdb9a328b..52c3215fef49 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1729,6 +1729,10 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) drm_encoder_helper_add(encoder, &vc4_dsi_encoder_helper_funcs); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + ret = drm_bridge_attach(encoder, dsi->bridge, NULL, 0); if (ret) return ret; @@ -1741,8 +1745,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) vc4_debugfs_add_regset32(drm, dsi->variant->debugfs_name, &dsi->regset); - pm_runtime_enable(dev); - return 0; } @@ -1752,8 +1754,6 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, struct vc4_dsi *dsi = dev_get_drvdata(dev); struct drm_encoder *encoder = &dsi->encoder.base; - pm_runtime_disable(dev); - /* * Restore the bridge_chain so the bridge detach procedure can happen * normally. From b4f2c70c1a7a0a7708c9755a9946452ee23adeb6 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:07 +0200 Subject: [PATCH 083/396] drm/vc4: hdmi: Switch to drmm_kzalloc Our internal structure that stores the DRM entities structure is allocated through a device-managed kzalloc. This means that this will eventually be freed whenever the device is removed. In our case, the most likely source of removal is that the main device is going to be unbound, and component_unbind_all() is being run. However, it occurs while the DRM device is still registered, which will create dangling pointers, eventually resulting in use-after-free. Switch to a DRM-managed allocation to keep our structure until the DRM driver doesn't need it anymore. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-38-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 73fb2f91c3e4..fba549edcfc5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2907,9 +2907,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) struct device_node *ddc_node; int ret; - vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); + vc4_hdmi = drmm_kzalloc(drm, sizeof(*vc4_hdmi), GFP_KERNEL); if (!vc4_hdmi) return -ENOMEM; + mutex_init(&vc4_hdmi->mutex); spin_lock_init(&vc4_hdmi->hw_lock); INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); From 7a951e3a26920ae424f563f63925bf478b37d00b Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:08 +0200 Subject: [PATCH 084/396] drm/vc4: hdmi: Remove call to drm_connector_unregister() drm_connector_unregister() is only to be used for connectors that have been registered through drm_connector_register() after drm_dev_register() has been called. This is our case here so let's remove the call. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-39-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index fba549edcfc5..05f769474903 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -267,12 +267,6 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) return connector_status_disconnected; } -static void vc4_hdmi_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) { struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); @@ -380,7 +374,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { .detect = vc4_hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_hdmi_connector_destroy, + .destroy = drm_connector_cleanup, .reset = vc4_hdmi_connector_reset, .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, @@ -3022,7 +3016,7 @@ err_free_cec: err_free_hotplug: vc4_hdmi_hotplug_exit(vc4_hdmi); err_destroy_conn: - vc4_hdmi_connector_destroy(&vc4_hdmi->connector); + drm_connector_cleanup(&vc4_hdmi->connector); err_destroy_encoder: drm_encoder_cleanup(encoder); pm_runtime_put_sync(dev); @@ -3066,7 +3060,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, vc4_hdmi_audio_exit(vc4_hdmi); vc4_hdmi_cec_exit(vc4_hdmi); vc4_hdmi_hotplug_exit(vc4_hdmi); - vc4_hdmi_connector_destroy(&vc4_hdmi->connector); + drm_connector_cleanup(&vc4_hdmi->connector); drm_encoder_cleanup(&vc4_hdmi->encoder.base); pm_runtime_disable(dev); From 56924791cd5de99374a027cf00ce9b6e55d74203 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:09 +0200 Subject: [PATCH 085/396] drm/vc4: hdmi: Switch to DRM-managed encoder initialization The current code will call drm_encoder_cleanup() when the device is unbound. However, by then, there might still be some references held to that encoder, including by the userspace that might still have the DRM device open. Let's switch to a DRM-managed initialization to clean up after ourselves only once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-40-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 05f769474903..6c44faea4af1 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2984,12 +2984,18 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); } - drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); + ret = drmm_encoder_init(drm, encoder, + NULL, + DRM_MODE_ENCODER_TMDS, + NULL); + if (ret) + goto err_put_runtime_pm; + drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs); ret = vc4_hdmi_connector_init(drm, vc4_hdmi); if (ret) - goto err_destroy_encoder; + goto err_put_runtime_pm; ret = vc4_hdmi_hotplug_init(vc4_hdmi); if (ret) @@ -3017,8 +3023,7 @@ err_free_hotplug: vc4_hdmi_hotplug_exit(vc4_hdmi); err_destroy_conn: drm_connector_cleanup(&vc4_hdmi->connector); -err_destroy_encoder: - drm_encoder_cleanup(encoder); +err_put_runtime_pm: pm_runtime_put_sync(dev); err_disable_runtime_pm: pm_runtime_disable(dev); @@ -3061,7 +3066,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, vc4_hdmi_cec_exit(vc4_hdmi); vc4_hdmi_hotplug_exit(vc4_hdmi); drm_connector_cleanup(&vc4_hdmi->connector); - drm_encoder_cleanup(&vc4_hdmi->encoder.base); pm_runtime_disable(dev); From 19d094c3a17d228381d4f1a25158a7b91b0e294f Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:10 +0200 Subject: [PATCH 086/396] drm/vc4: hdmi: Switch to DRM-managed connector initialization The current code will call drm_connector_unregister() and drm_connector_cleanup() when the device is unbound. However, by then, there might still be some references held to that connector, including by the userspace that might still have the DRM device open. Let's switch to a DRM-managed initialization to clean up after ourselves only once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-41-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 6c44faea4af1..283fea78f3cf 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -374,7 +374,6 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { .detect = vc4_hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, .reset = vc4_hdmi_connector_reset, .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, @@ -392,10 +391,13 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, struct drm_encoder *encoder = &vc4_hdmi->encoder.base; int ret; - drm_connector_init_with_ddc(dev, connector, - &vc4_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA, - vc4_hdmi->ddc); + ret = drmm_connector_init(dev, connector, + &vc4_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + vc4_hdmi->ddc); + if (ret) + return ret; + drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); /* @@ -2999,7 +3001,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) ret = vc4_hdmi_hotplug_init(vc4_hdmi); if (ret) - goto err_destroy_conn; + goto err_put_runtime_pm; ret = vc4_hdmi_cec_init(vc4_hdmi); if (ret) @@ -3021,8 +3023,6 @@ err_free_cec: vc4_hdmi_cec_exit(vc4_hdmi); err_free_hotplug: vc4_hdmi_hotplug_exit(vc4_hdmi); -err_destroy_conn: - drm_connector_cleanup(&vc4_hdmi->connector); err_put_runtime_pm: pm_runtime_put_sync(dev); err_disable_runtime_pm: @@ -3065,7 +3065,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, vc4_hdmi_audio_exit(vc4_hdmi); vc4_hdmi_cec_exit(vc4_hdmi); vc4_hdmi_hotplug_exit(vc4_hdmi); - drm_connector_cleanup(&vc4_hdmi->connector); pm_runtime_disable(dev); From 59f9d46af43c884b92f690934263196387437c7e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:11 +0200 Subject: [PATCH 087/396] drm/vc4: hdmi: Switch to device-managed ALSA initialization The current code to unregister our ALSA device needs to be undone manually when we remove the HDMI driver. Since ALSA doesn't seem to support any mechanism to defer freeing something until the last user of the ALSA device is gone, we can either use a device-managed or a DRM-managed action. The consistent way would be to use a DRM-managed one, just like pretty much any framework-facing structure should be doing. However, ALSA does a lot of allocation and registration using device-managed calls. Thus, if we're going that way, by the time the DRM-managed action would run all of those allocation would have been freed and we would end up with a use-after-free. Thus, let's do a device-managed action. It's been tested with KASAN enabled and doesn't seem to trigger any issue, so it's as good as anything. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-42-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 43 ++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 283fea78f3cf..bf7d56bbcba0 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2056,6 +2056,14 @@ static struct hdmi_codec_pdata vc4_hdmi_codec_pdata = { .i2s = 1, }; +static void vc4_hdmi_audio_codec_release(void *ptr) +{ + struct vc4_hdmi *vc4_hdmi = ptr; + + platform_device_unregister(vc4_hdmi->audio.codec_pdev); + vc4_hdmi->audio.codec_pdev = NULL; +} + static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) { const struct vc4_hdmi_register *mai_data = @@ -2097,6 +2105,30 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; vc4_hdmi->audio.dma_data.maxburst = 2; + /* + * NOTE: Strictly speaking, we should probably use a DRM-managed + * registration there to avoid removing all the audio components + * by the time the driver doesn't have any user anymore. + * + * However, the ASoC core uses a number of devm_kzalloc calls + * when registering, even when using non-device-managed + * functions (such as in snd_soc_register_component()). + * + * If we call snd_soc_unregister_component() in a DRM-managed + * action, the device-managed actions have already been executed + * and thus we would access memory that has been freed. + * + * Using device-managed hooks here probably leaves us open to a + * bunch of issues if userspace still has a handle on the ALSA + * device when the device is removed. However, this is mitigated + * by the use of drm_dev_enter()/drm_dev_exit() in the audio + * path to prevent the access to the device resources if it + * isn't there anymore. + * + * Then, the vc4_hdmi structure is DRM-managed and thus only + * freed whenever the last user has closed the DRM device file. + * It should thus outlive ALSA in most situations. + */ ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0); if (ret) { dev_err(dev, "Could not register PCM component: %d\n", ret); @@ -2120,6 +2152,10 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) } vc4_hdmi->audio.codec_pdev = codec_pdev; + ret = devm_add_action_or_reset(dev, vc4_hdmi_audio_codec_release, vc4_hdmi); + if (ret) + return ret; + dai_link->cpus = &vc4_hdmi->audio.cpu; dai_link->codecs = &vc4_hdmi->audio.codec; dai_link->platforms = &vc4_hdmi->audio.platform; @@ -2158,12 +2194,6 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) } -static void vc4_hdmi_audio_exit(struct vc4_hdmi *vc4_hdmi) -{ - platform_device_unregister(vc4_hdmi->audio.codec_pdev); - vc4_hdmi->audio.codec_pdev = NULL; -} - static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv) { struct vc4_hdmi *vc4_hdmi = priv; @@ -3062,7 +3092,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, kfree(vc4_hdmi->hdmi_regset.regs); kfree(vc4_hdmi->hd_regset.regs); - vc4_hdmi_audio_exit(vc4_hdmi); vc4_hdmi_cec_exit(vc4_hdmi); vc4_hdmi_hotplug_exit(vc4_hdmi); From 015653f7af7cb7fa56e9a88af2a15c814a39b6b4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:12 +0200 Subject: [PATCH 088/396] drm/vc4: hdmi: Switch to device-managed CEC initialization The current code to unregister our CEC device needs to be undone manually when we remove the HDMI driver. Since the CEC framework will allocate its main structure, and will defer its deallocation to when the last user will have closed it, we don't really need to take any particular measure to prevent any use-after-free and can thus use any managed action. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-43-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 94 ++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index bf7d56bbcba0..83ca1c02dde2 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2576,6 +2576,14 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = { .adap_transmit = vc4_hdmi_cec_adap_transmit, }; +static void vc4_hdmi_cec_release(void *ptr) +{ + struct vc4_hdmi *vc4_hdmi = ptr; + + cec_unregister_adapter(vc4_hdmi->cec_adap); + vc4_hdmi->cec_adap = NULL; +} + static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) { struct cec_connector_info conn_info; @@ -2600,70 +2608,71 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); if (vc4_hdmi->variant->external_irq_controller) { - ret = request_threaded_irq(platform_get_irq_byname(pdev, "cec-rx"), - vc4_cec_irq_handler_rx_bare, - vc4_cec_irq_handler_rx_thread, 0, - "vc4 hdmi cec rx", vc4_hdmi); + ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-rx"), + vc4_cec_irq_handler_rx_bare, + vc4_cec_irq_handler_rx_thread, 0, + "vc4 hdmi cec rx", vc4_hdmi); if (ret) goto err_delete_cec_adap; - ret = request_threaded_irq(platform_get_irq_byname(pdev, "cec-tx"), - vc4_cec_irq_handler_tx_bare, - vc4_cec_irq_handler_tx_thread, 0, - "vc4 hdmi cec tx", vc4_hdmi); + ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-tx"), + vc4_cec_irq_handler_tx_bare, + vc4_cec_irq_handler_tx_thread, 0, + "vc4 hdmi cec tx", vc4_hdmi); if (ret) - goto err_remove_cec_rx_handler; + goto err_delete_cec_adap; } else { - ret = request_threaded_irq(platform_get_irq(pdev, 0), - vc4_cec_irq_handler, - vc4_cec_irq_handler_thread, 0, - "vc4 hdmi cec", vc4_hdmi); + ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), + vc4_cec_irq_handler, + vc4_cec_irq_handler_thread, 0, + "vc4 hdmi cec", vc4_hdmi); if (ret) goto err_delete_cec_adap; } ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev); if (ret < 0) - goto err_remove_handlers; + goto err_delete_cec_adap; + + /* + * NOTE: Strictly speaking, we should probably use a DRM-managed + * registration there to avoid removing the CEC adapter by the + * time the DRM driver doesn't have any user anymore. + * + * However, the CEC framework already cleans up the CEC adapter + * only when the last user has closed its file descriptor, so we + * don't need to handle it in DRM. + * + * By the time the device-managed hook is executed, we will give + * up our reference to the CEC adapter and therefore don't + * really care when it's actually freed. + * + * There's still a problematic sequence: if we unregister our + * CEC adapter, but the userspace keeps a handle on the CEC + * adapter but not the DRM device for some reason. In such a + * case, our vc4_hdmi structure will be freed, but the + * cec_adapter structure will have a dangling pointer to what + * used to be our HDMI controller. If we get a CEC call at that + * moment, we could end up with a use-after-free. Fortunately, + * the CEC framework already handles this too, by calling + * cec_is_registered() in cec_ioctl() and cec_poll(). + */ + ret = devm_add_action_or_reset(dev, vc4_hdmi_cec_release, vc4_hdmi); + if (ret) + return ret; return 0; -err_remove_handlers: - if (vc4_hdmi->variant->external_irq_controller) - free_irq(platform_get_irq_byname(pdev, "cec-tx"), vc4_hdmi); - else - free_irq(platform_get_irq(pdev, 0), vc4_hdmi); - -err_remove_cec_rx_handler: - if (vc4_hdmi->variant->external_irq_controller) - free_irq(platform_get_irq_byname(pdev, "cec-rx"), vc4_hdmi); - err_delete_cec_adap: cec_delete_adapter(vc4_hdmi->cec_adap); return ret; } - -static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) -{ - struct platform_device *pdev = vc4_hdmi->pdev; - - if (vc4_hdmi->variant->external_irq_controller) { - free_irq(platform_get_irq_byname(pdev, "cec-rx"), vc4_hdmi); - free_irq(platform_get_irq_byname(pdev, "cec-tx"), vc4_hdmi); - } else { - free_irq(platform_get_irq(pdev, 0), vc4_hdmi); - } - - cec_unregister_adapter(vc4_hdmi->cec_adap); -} #else static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) { return 0; } - -static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {}; #endif static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, @@ -3039,7 +3048,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) ret = vc4_hdmi_audio_init(vc4_hdmi); if (ret) - goto err_free_cec; + goto err_free_hotplug; vc4_debugfs_add_file(drm, variant->debugfs_name, vc4_hdmi_debugfs_regs, @@ -3049,8 +3058,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) return 0; -err_free_cec: - vc4_hdmi_cec_exit(vc4_hdmi); err_free_hotplug: vc4_hdmi_hotplug_exit(vc4_hdmi); err_put_runtime_pm: @@ -3092,7 +3099,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, kfree(vc4_hdmi->hdmi_regset.regs); kfree(vc4_hdmi->hd_regset.regs); - vc4_hdmi_cec_exit(vc4_hdmi); vc4_hdmi_hotplug_exit(vc4_hdmi); pm_runtime_disable(dev); From d3a84242f897506509d1bb29b8e64166958fb991 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:13 +0200 Subject: [PATCH 089/396] drm/vc4: hdmi: Use a device-managed action for DDC The reference to the DDC controller device needs to be put back when we're done with it. Let's use a device-managed action to simplify the driver. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-44-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 83ca1c02dde2..274f17880455 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2932,6 +2932,13 @@ static int vc4_hdmi_runtime_resume(struct device *dev) return 0; } +static void vc4_hdmi_put_ddc_device(void *ptr) +{ + struct vc4_hdmi *vc4_hdmi = ptr; + + put_device(&vc4_hdmi->ddc->dev); +} + static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) { const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); @@ -2987,13 +2994,16 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) return -EPROBE_DEFER; } + ret = devm_add_action_or_reset(dev, vc4_hdmi_put_ddc_device, vc4_hdmi); + if (ret) + return ret; + /* Only use the GPIO HPD pin if present in the DT, otherwise * we'll use the HDMI core's register. */ vc4_hdmi->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); if (IS_ERR(vc4_hdmi->hpd_gpio)) { - ret = PTR_ERR(vc4_hdmi->hpd_gpio); - goto err_put_ddc; + return PTR_ERR(vc4_hdmi->hpd_gpio); } vc4_hdmi->disable_wifi_frequencies = @@ -3064,8 +3074,6 @@ err_put_runtime_pm: pm_runtime_put_sync(dev); err_disable_runtime_pm: pm_runtime_disable(dev); -err_put_ddc: - put_device(&vc4_hdmi->ddc->dev); return ret; } @@ -3102,8 +3110,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, vc4_hdmi_hotplug_exit(vc4_hdmi); pm_runtime_disable(dev); - - put_device(&vc4_hdmi->ddc->dev); } static const struct component_ops vc4_hdmi_ops = { From a3dbb1c016576838a1591d2341641cb4067840e8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:14 +0200 Subject: [PATCH 090/396] drm/vc4: hdmi: Switch to DRM-managed kfree to build regsets The current code to build the registers set later exposed in debugfs for the HDMI controller relies on traditional allocations, that are later free'd as part of the driver unbind hook. Since krealloc doesn't have a DRM-managed equivalent, let's add an action to free the buffer later on. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-45-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++++------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 3 ++- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 274f17880455..c93100fe4b42 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2675,7 +2675,15 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) } #endif -static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, +static void vc4_hdmi_free_regset(struct drm_device *drm, void *ptr) +{ + struct debugfs_reg32 *regs = ptr; + + kfree(regs); +} + +static int vc4_hdmi_build_regset(struct drm_device *drm, + struct vc4_hdmi *vc4_hdmi, struct debugfs_regset32 *regset, enum vc4_hdmi_regs reg) { @@ -2683,6 +2691,7 @@ static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, struct debugfs_reg32 *regs, *new_regs; unsigned int count = 0; unsigned int i; + int ret; regs = kcalloc(variant->num_registers, sizeof(*regs), GFP_KERNEL); @@ -2708,10 +2717,15 @@ static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, regset->regs = new_regs; regset->nregs = count; + ret = drmm_add_action_or_reset(drm, vc4_hdmi_free_regset, new_regs); + if (ret) + return ret; + return 0; } -static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) +static int vc4_hdmi_init_resources(struct drm_device *drm, + struct vc4_hdmi *vc4_hdmi) { struct platform_device *pdev = vc4_hdmi->pdev; struct device *dev = &pdev->dev; @@ -2725,11 +2739,11 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) if (IS_ERR(vc4_hdmi->hd_regs)) return PTR_ERR(vc4_hdmi->hd_regs); - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); if (ret) return ret; @@ -2752,7 +2766,8 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return 0; } -static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) +static int vc5_hdmi_init_resources(struct drm_device *drm, + struct vc4_hdmi *vc4_hdmi) { struct platform_device *pdev = vc4_hdmi->pdev; struct device *dev = &pdev->dev; @@ -2854,35 +2869,35 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return PTR_ERR(vc4_hdmi->reset); } - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM); if (ret) return ret; - ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM); + ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM); if (ret) return ret; @@ -2977,7 +2992,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK) vc4_hdmi->scdc_enabled = true; - ret = variant->init_resources(vc4_hdmi); + ret = variant->init_resources(drm, vc4_hdmi); if (ret) return ret; @@ -3104,9 +3119,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0); vc4_hdmi = dev_get_drvdata(dev); - kfree(vc4_hdmi->hdmi_regset.regs); - kfree(vc4_hdmi->hd_regset.regs); - vc4_hdmi_hotplug_exit(vc4_hdmi); pm_runtime_disable(dev); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index c3ed2b07df23..99b0bc1297be 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -58,7 +58,8 @@ struct vc4_hdmi_variant { /* Callback to get the resources (memory region, interrupts, * clocks, etc) for that variant. */ - int (*init_resources)(struct vc4_hdmi *vc4_hdmi); + int (*init_resources)(struct drm_device *drm, + struct vc4_hdmi *vc4_hdmi); /* Callback to reset the HDMI block */ void (*reset)(struct vc4_hdmi *vc4_hdmi); From af8a3b125b682c4c582bb25342af4759d9b4a1e5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:15 +0200 Subject: [PATCH 091/396] drm/vc4: hdmi: Use devm to register hotplug interrupts Commit 776efe800fed ("drm/vc4: hdmi: Drop devm interrupt handler for hotplug interrupts") dropped the device-managed interrupt registration because it was creating bugs and races whenever an interrupt was coming in while the device was removed. However, our latest patches to the HDMI controller driver fix this as well, so we can use device-managed interrupt handlers again. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-46-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 41 +++++++++------------------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c93100fe4b42..6275db463afd 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2216,21 +2216,19 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi) unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected"); unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed"); - ret = request_threaded_irq(hpd_con, - NULL, - vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, - "vc4 hdmi hpd connected", vc4_hdmi); + ret = devm_request_threaded_irq(&pdev->dev, hpd_con, + NULL, + vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, + "vc4 hdmi hpd connected", vc4_hdmi); if (ret) return ret; - ret = request_threaded_irq(hpd_rm, - NULL, - vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, - "vc4 hdmi hpd disconnected", vc4_hdmi); - if (ret) { - free_irq(hpd_con, vc4_hdmi); + ret = devm_request_threaded_irq(&pdev->dev, hpd_rm, + NULL, + vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT, + "vc4 hdmi hpd disconnected", vc4_hdmi); + if (ret) return ret; - } connector->polled = DRM_CONNECTOR_POLL_HPD; } @@ -2238,16 +2236,6 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi) return 0; } -static void vc4_hdmi_hotplug_exit(struct vc4_hdmi *vc4_hdmi) -{ - struct platform_device *pdev = vc4_hdmi->pdev; - - if (vc4_hdmi->variant->external_irq_controller) { - free_irq(platform_get_irq_byname(pdev, "hpd-connected"), vc4_hdmi); - free_irq(platform_get_irq_byname(pdev, "hpd-removed"), vc4_hdmi); - } -} - #ifdef CONFIG_DRM_VC4_HDMI_CEC static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv) { @@ -3069,11 +3057,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) ret = vc4_hdmi_cec_init(vc4_hdmi); if (ret) - goto err_free_hotplug; + goto err_put_runtime_pm; ret = vc4_hdmi_audio_init(vc4_hdmi); if (ret) - goto err_free_hotplug; + goto err_put_runtime_pm; vc4_debugfs_add_file(drm, variant->debugfs_name, vc4_hdmi_debugfs_regs, @@ -3083,8 +3071,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) return 0; -err_free_hotplug: - vc4_hdmi_hotplug_exit(vc4_hdmi); err_put_runtime_pm: pm_runtime_put_sync(dev); err_disable_runtime_pm: @@ -3096,8 +3082,6 @@ err_disable_runtime_pm: static void vc4_hdmi_unbind(struct device *dev, struct device *master, void *data) { - struct vc4_hdmi *vc4_hdmi; - /* * ASoC makes it a bit hard to retrieve a pointer to the * vc4_hdmi structure. Registering the card will overwrite our @@ -3117,9 +3101,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, */ BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0); BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0); - vc4_hdmi = dev_get_drvdata(dev); - - vc4_hdmi_hotplug_exit(vc4_hdmi); pm_runtime_disable(dev); } From 0c9d0ddd9cf4b43f8b3faf752c5a1aaa665ed099 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:16 +0200 Subject: [PATCH 092/396] drm/vc4: hdmi: Move audio structure offset checks The HDMI driver unbind hook doesn't have any ALSA-related code anymore, so let's move the ALSA sanity checks and comments we have to some other part of the driver dedicated to ALSA. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-47-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 6275db463afd..a130b7d48e46 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2076,6 +2076,26 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) int index, len; int ret; + /* + * ASoC makes it a bit hard to retrieve a pointer to the + * vc4_hdmi structure. Registering the card will overwrite our + * device drvdata with a pointer to the snd_soc_card structure, + * which can then be used to retrieve whatever drvdata we want + * to associate. + * + * However, that doesn't fly in the case where we wouldn't + * register an ASoC card (because of an old DT that is missing + * the dmas properties for example), then the card isn't + * registered and the device drvdata wouldn't be set. + * + * We can deal with both cases by making sure a snd_soc_card + * pointer and a vc4_hdmi structure are pointing to the same + * memory address, so we can treat them indistinctly without any + * issue. + */ + BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0); + BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0); + if (!of_find_property(dev->of_node, "dmas", &len) || !len) { dev_warn(dev, "'dmas' DT property is missing or empty, no HDMI audio\n"); @@ -3082,26 +3102,6 @@ err_disable_runtime_pm: static void vc4_hdmi_unbind(struct device *dev, struct device *master, void *data) { - /* - * ASoC makes it a bit hard to retrieve a pointer to the - * vc4_hdmi structure. Registering the card will overwrite our - * device drvdata with a pointer to the snd_soc_card structure, - * which can then be used to retrieve whatever drvdata we want - * to associate. - * - * However, that doesn't fly in the case where we wouldn't - * register an ASoC card (because of an old DT that is missing - * the dmas properties for example), then the card isn't - * registered and the device drvdata wouldn't be set. - * - * We can deal with both cases by making sure a snd_soc_card - * pointer and a vc4_hdmi structure are pointing to the same - * memory address, so we can treat them indistinctly without any - * issue. - */ - BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0); - BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0); - pm_runtime_disable(dev); } From cd00ed5187bff03d4c2ba143a5993383dd6ed66c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:17 +0200 Subject: [PATCH 093/396] drm/vc4: hdmi: Protect device resources after removal Whenever the device and driver are unbound, the main device and all the subdevices will be removed by calling their unbind() method. However, the DRM device itself will only be freed when the last user will have closed it. It means that there is a time window where the device and its resources aren't there anymore, but the userspace can still call into our driver. Fortunately, the DRM framework provides the drm_dev_enter() and drm_dev_exit() functions to make sure our underlying device is still there for the section protected by those calls. Let's add them to the HDMI driver. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-48-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 308 +++++++++++++++++++++++++++++++-- 1 file changed, 291 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index a130b7d48e46..a826faf8b02d 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -34,6 +34,7 @@ #include <drm/display/drm_hdmi_helper.h> #include <drm/display/drm_scdc_helper.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <linux/clk.h> @@ -146,7 +147,12 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct vc4_hdmi *vc4_hdmi = node->info_ent->data; + struct drm_device *drm = vc4_hdmi->connector.dev; struct drm_printer p = drm_seq_file_printer(m); + int idx; + + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); drm_print_regset32(&p, &vc4_hdmi->hd_regset); @@ -157,12 +163,23 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) drm_print_regset32(&p, &vc4_hdmi->ram_regset); drm_print_regset32(&p, &vc4_hdmi->rm_regset); + drm_dev_exit(idx); + return 0; } static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) { + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int idx; + + /* + * We can be called by our bind callback, when the + * connector->dev pointer might not be initialised yet. + */ + if (drm && !drm_dev_enter(drm, &idx)) + return; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -179,11 +196,23 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + if (drm) + drm_dev_exit(idx); } static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) { + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int idx; + + /* + * We can be called by our bind callback, when the + * connector->dev pointer might not be initialised yet. + */ + if (drm && !drm_dev_enter(drm, &idx)) + return; reset_control_reset(vc4_hdmi->reset); @@ -195,15 +224,31 @@ static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + if (drm) + drm_dev_exit(idx); } #ifdef CONFIG_DRM_VC4_HDMI_CEC static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) { - unsigned long cec_rate = clk_get_rate(vc4_hdmi->cec_clock); + struct drm_device *drm = vc4_hdmi->connector.dev; + unsigned long cec_rate; unsigned long flags; u16 clk_cnt; u32 value; + int idx; + + /* + * This function is called by our runtime_resume implementation + * and thus at bind time, when we haven't registered our + * connector yet and thus don't have a pointer to the DRM + * device. + */ + if (drm && !drm_dev_enter(drm, &idx)) + return; + + cec_rate = clk_get_rate(vc4_hdmi->cec_clock); spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -219,6 +264,9 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) HDMI_WRITE(HDMI_CEC_CNTRL_1, value); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + if (drm) + drm_dev_exit(idx); } #else static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} @@ -440,25 +488,34 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, bool poll) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; u32 packet_id = type - 0x80; unsigned long flags; + int ret = 0; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - if (!poll) - return 0; + if (poll) { + ret = wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) & + BIT(packet_id)), 100); + } - return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) & - BIT(packet_id)), 100); + drm_dev_exit(idx); + return ret; } static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, union hdmi_infoframe *frame) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; u32 packet_id = frame->any.type - 0x80; const struct vc4_hdmi_register *ram_packet_start = &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; @@ -471,6 +528,10 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, unsigned long flags; ssize_t len, i; int ret; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & VC4_HDMI_RAM_PACKET_ENABLE), @@ -478,12 +539,12 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); if (len < 0) - return; + goto out; ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true); if (ret) { DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret); - return; + goto out; } spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -519,6 +580,9 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, BIT(packet_id)), 100); if (ret) DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); + +out: + drm_dev_exit(idx); } static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, @@ -668,8 +732,10 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; unsigned long flags; + int idx; lockdep_assert_held(&vc4_hdmi->mutex); @@ -681,6 +747,9 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) vc4_hdmi->output_format)) return; + if (!drm_dev_enter(drm, &idx)) + return; + drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); drm_scdc_set_scrambling(vc4_hdmi->ddc, true); @@ -689,6 +758,8 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) VC5_HDMI_SCRAMBLER_CTL_ENABLE); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + drm_dev_exit(idx); + vc4_hdmi->scdc_enabled = true; queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, @@ -698,7 +769,9 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int idx; lockdep_assert_held(&vc4_hdmi->mutex); @@ -710,6 +783,9 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) if (delayed_work_pending(&vc4_hdmi->scrambling_work)) cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); + if (!drm_dev_enter(drm, &idx)) + return; + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) & ~VC5_HDMI_SCRAMBLER_CTL_ENABLE); @@ -717,6 +793,8 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) drm_scdc_set_scrambling(vc4_hdmi->ddc, false); drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false); + + drm_dev_exit(idx); } static void vc4_hdmi_scrambling_wq(struct work_struct *work) @@ -739,12 +817,17 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int idx; mutex_lock(&vc4_hdmi->mutex); vc4_hdmi->packet_ram_enabled = false; + if (!drm_dev_enter(drm, &idx)) + goto out; + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); @@ -762,6 +845,9 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, vc4_hdmi_disable_scrambling(encoder); + drm_dev_exit(idx); + +out: mutex_unlock(&vc4_hdmi->mutex); } @@ -769,11 +855,16 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; int ret; + int idx; mutex_lock(&vc4_hdmi->mutex); + if (!drm_dev_enter(drm, &idx)) + goto out; + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); @@ -789,6 +880,9 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, if (ret < 0) DRM_ERROR("Failed to release power domain: %d\n", ret); + drm_dev_exit(idx); + +out: mutex_unlock(&vc4_hdmi->mutex); } @@ -796,8 +890,13 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; u32 csc_ctl; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -832,6 +931,8 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + drm_dev_exit(idx); } /* @@ -916,6 +1017,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { + struct drm_device *drm = vc4_hdmi->connector.dev; struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(state); unsigned long flags; @@ -924,6 +1026,10 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, u32 csc_chan_ctl = 0; u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, VC5_MT_CP_CSC_CTL_MODE); + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -966,12 +1072,15 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + drm_dev_exit(idx); } static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, struct drm_display_mode *mode) { + struct drm_device *drm = vc4_hdmi->connector.dev; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -991,6 +1100,10 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, VC4_HDMI_VERTB_VBP)); unsigned long flags; u32 reg; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -1023,12 +1136,15 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_MISC_CONTROL, reg); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + drm_dev_exit(idx); } static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, struct drm_display_mode *mode) { + struct drm_device *drm = vc4_hdmi->connector.dev; const struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(state); bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; @@ -1052,6 +1168,10 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, unsigned char gcp; bool gcp_en; u32 reg; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -1128,13 +1248,20 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_CLOCK_STOP, 0); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + drm_dev_exit(idx); } static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) { + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; u32 drift; int ret; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -1163,12 +1290,15 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); WARN_ONCE(ret, "Timeout waiting for " "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); + + drm_dev_exit(idx); } static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; struct drm_connector *connector = &vc4_hdmi->connector; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); @@ -1179,9 +1309,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, unsigned long bvb_rate, hsm_rate; unsigned long flags; int ret; + int idx; mutex_lock(&vc4_hdmi->mutex); + if (!drm_dev_enter(drm, &idx)) + goto out; + /* * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must * be faster than pixel clock, infinitesimally faster, tested in @@ -1202,13 +1336,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); - goto out; + goto err_dev_exit; } ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to retain power domain: %d\n", ret); - goto out; + goto err_dev_exit; } ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); @@ -1260,6 +1394,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, if (vc4_hdmi->variant->set_timings) vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); + drm_dev_exit(idx); + mutex_unlock(&vc4_hdmi->mutex); return; @@ -1268,6 +1404,8 @@ err_disable_pixel_clock: clk_disable_unprepare(vc4_hdmi->pixel_clock); err_put_runtime_pm: pm_runtime_put(&vc4_hdmi->pdev->dev); +err_dev_exit: + drm_dev_exit(idx); out: mutex_unlock(&vc4_hdmi->mutex); return; @@ -1277,14 +1415,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; struct drm_connector *connector = &vc4_hdmi->connector; struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); unsigned long flags; + int idx; mutex_lock(&vc4_hdmi->mutex); + if (!drm_dev_enter(drm, &idx)) + return; + if (vc4_hdmi->variant->csc_setup) vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode); @@ -1292,6 +1435,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + drm_dev_exit(idx); + mutex_unlock(&vc4_hdmi->mutex); } @@ -1299,15 +1444,20 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; struct drm_display_info *display = &vc4_hdmi->connector.display_info; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; unsigned long flags; int ret; + int idx; mutex_lock(&vc4_hdmi->mutex); + if (!drm_dev_enter(drm, &idx)) + return; + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_VID_CTL, @@ -1366,6 +1516,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, vc4_hdmi_recenter_fifo(vc4_hdmi); vc4_hdmi_enable_scrambling(encoder); + drm_dev_exit(idx); mutex_unlock(&vc4_hdmi->mutex); } @@ -1714,13 +1865,20 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi) { + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; u32 hotplug; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return false; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); hotplug = HDMI_READ(HDMI_HOTPLUG); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + drm_dev_exit(idx); + return !!(hotplug & VC4_HDMI_HOTPLUG_CONNECTED); } @@ -1728,10 +1886,16 @@ static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) { - u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); + struct drm_device *drm = vc4_hdmi->connector.dev; + u32 hsm_clock; unsigned long flags; unsigned long n, m; + int idx; + if (!drm_dev_enter(drm, &idx)) + return; + + hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); rational_best_approximation(hsm_clock, samplerate, VC4_HD_MAI_SMP_N_MASK >> VC4_HD_MAI_SMP_N_SHIFT, @@ -1744,6 +1908,8 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) | VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + drm_dev_exit(idx); } static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) @@ -1799,13 +1965,21 @@ static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi) static int vc4_hdmi_audio_startup(struct device *dev, void *data) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int ret = 0; + int idx; mutex_lock(&vc4_hdmi->mutex); + if (!drm_dev_enter(drm, &idx)) { + ret = -ENODEV; + goto out; + } + if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) { - mutex_unlock(&vc4_hdmi->mutex); - return -ENODEV; + ret = -ENODEV; + goto out_dev_exit; } vc4_hdmi->audio.streaming = true; @@ -1822,9 +1996,12 @@ static int vc4_hdmi_audio_startup(struct device *dev, void *data) if (vc4_hdmi->variant->phy_rng_enable) vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); +out_dev_exit: + drm_dev_exit(idx); +out: mutex_unlock(&vc4_hdmi->mutex); - return 0; + return ret; } static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) @@ -1853,10 +2030,15 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_audio_shutdown(struct device *dev, void *data) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int idx; mutex_lock(&vc4_hdmi->mutex); + if (!drm_dev_enter(drm, &idx)) + goto out; + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_MAI_CTL, @@ -1872,6 +2054,9 @@ static void vc4_hdmi_audio_shutdown(struct device *dev, void *data) vc4_hdmi->audio.streaming = false; vc4_hdmi_audio_reset(vc4_hdmi); + drm_dev_exit(idx); + +out: mutex_unlock(&vc4_hdmi->mutex); } @@ -1919,6 +2104,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, struct hdmi_codec_params *params) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + struct drm_device *drm = vc4_hdmi->connector.dev; struct drm_encoder *encoder = &vc4_hdmi->encoder.base; unsigned int sample_rate = params->sample_rate; unsigned int channels = params->channels; @@ -1927,15 +2113,22 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, u32 channel_map; u32 mai_audio_format; u32 mai_sample_rate; + int ret = 0; + int idx; dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__, sample_rate, params->sample_width, channels); mutex_lock(&vc4_hdmi->mutex); + if (!drm_dev_enter(drm, &idx)) { + ret = -ENODEV; + goto out; + } + if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) { - mutex_unlock(&vc4_hdmi->mutex); - return -EINVAL; + ret = -EINVAL; + goto out_dev_exit; } vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate); @@ -1992,9 +2185,12 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); vc4_hdmi_set_audio_infoframe(encoder); +out_dev_exit: + drm_dev_exit(idx); +out: mutex_unlock(&vc4_hdmi->mutex); - return 0; + return ret; } static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = { @@ -2329,6 +2525,17 @@ static irqreturn_t vc4_cec_irq_handler_tx_bare_locked(struct vc4_hdmi *vc4_hdmi) { u32 cntrl1; + /* + * We don't need to protect the register access using + * drm_dev_enter() there because the interrupt handler lifetime + * is tied to the device itself, and not to the DRM device. + * + * So when the device will be gone, one of the first thing we + * will be doing will be to unregister the interrupt handler, + * and then unregister the DRM device. drm_dev_enter() would + * thus always succeed if we are here. + */ + lockdep_assert_held(&vc4_hdmi->hw_lock); cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); @@ -2357,6 +2564,17 @@ static irqreturn_t vc4_cec_irq_handler_rx_bare_locked(struct vc4_hdmi *vc4_hdmi) lockdep_assert_held(&vc4_hdmi->hw_lock); + /* + * We don't need to protect the register access using + * drm_dev_enter() there because the interrupt handler lifetime + * is tied to the device itself, and not to the DRM device. + * + * So when the device will be gone, one of the first thing we + * will be doing will be to unregister the interrupt handler, + * and then unregister the DRM device. drm_dev_enter() would + * thus always succeed if we are here. + */ + vc4_hdmi->cec_rx_msg.len = 0; cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); vc4_cec_read_msg(vc4_hdmi, cntrl1); @@ -2388,6 +2606,17 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) irqreturn_t ret; u32 cntrl5; + /* + * We don't need to protect the register access using + * drm_dev_enter() there because the interrupt handler lifetime + * is tied to the device itself, and not to the DRM device. + * + * So when the device will be gone, one of the first thing we + * will be doing will be to unregister the interrupt handler, + * and then unregister the DRM device. drm_dev_enter() would + * thus always succeed if we are here. + */ + if (!(stat & VC4_HDMI_CPU_CEC)) return IRQ_NONE; @@ -2408,11 +2637,13 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) static int vc4_hdmi_cec_enable(struct cec_adapter *adap) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct drm_device *drm = vc4_hdmi->connector.dev; /* clock period in microseconds */ const u32 usecs = 1000000 / CEC_CLOCK_FREQ; unsigned long flags; u32 val; int ret; + int idx; /* * NOTE: This function should really take vc4_hdmi->mutex, but doing so @@ -2425,9 +2656,19 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) * keep it in mind if we were to change that assumption. */ + if (!drm_dev_enter(drm, &idx)) + /* + * We can't return an error code, because the CEC + * framework will emit WARN_ON messages at unbind + * otherwise. + */ + return 0; + ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); - if (ret) + if (ret) { + drm_dev_exit(idx); return ret; + } spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -2463,13 +2704,25 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + drm_dev_exit(idx); + return 0; } static int vc4_hdmi_cec_disable(struct cec_adapter *adap) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int idx; + + if (!drm_dev_enter(drm, &idx)) + /* + * We can't return an error code, because the CEC + * framework will emit WARN_ON messages at unbind + * otherwise. + */ + return 0; /* * NOTE: This function should really take vc4_hdmi->mutex, but doing so @@ -2494,6 +2747,8 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap) pm_runtime_put(&vc4_hdmi->pdev->dev); + drm_dev_exit(idx); + return 0; } @@ -2508,7 +2763,9 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; + int idx; /* * NOTE: This function should really take vc4_hdmi->mutex, but doing so @@ -2521,12 +2778,22 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) * keep it in mind if we were to change that assumption. */ + if (!drm_dev_enter(drm, &idx)) + /* + * We can't return an error code, because the CEC + * framework will emit WARN_ON messages at unbind + * otherwise. + */ + return 0; + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_CEC_CNTRL_1, (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + drm_dev_exit(idx); + return 0; } @@ -2538,6 +2805,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, unsigned long flags; u32 val; unsigned int i; + int idx; /* * NOTE: This function should really take vc4_hdmi->mutex, but doing so @@ -2550,8 +2818,12 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, * keep it in mind if we were to change that assumption. */ + if (!drm_dev_enter(dev, &idx)) + return -ENODEV; + if (msg->len > 16) { drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); + drm_dev_exit(idx); return -ENOMEM; } @@ -2575,6 +2847,8 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + drm_dev_exit(idx); + return 0; } From 932d860f46722cd91a9d012c94b2d32013a8ea15 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:18 +0200 Subject: [PATCH 094/396] drm/vc4: hdmi: Switch to devm_pm_runtime_enable devm_pm_runtime_enable() simplifies the driver a bit since it will call pm_runtime_disable() automatically through a device-managed action. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-49-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index a826faf8b02d..166d22d62d99 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -3314,7 +3314,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->disable_4kp60 = true; } - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; /* * We need to have the device powered up at this point to call @@ -3322,7 +3324,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) */ ret = pm_runtime_resume_and_get(dev); if (ret) - goto err_disable_runtime_pm; + return ret; if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && @@ -3367,21 +3369,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) err_put_runtime_pm: pm_runtime_put_sync(dev); -err_disable_runtime_pm: - pm_runtime_disable(dev); return ret; } -static void vc4_hdmi_unbind(struct device *dev, struct device *master, - void *data) -{ - pm_runtime_disable(dev); -} - static const struct component_ops vc4_hdmi_ops = { .bind = vc4_hdmi_bind, - .unbind = vc4_hdmi_unbind, }; static int vc4_hdmi_dev_probe(struct platform_device *pdev) From 121b1a5f47e5bcb6baafd2aea00761af2ca5ff36 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:19 +0200 Subject: [PATCH 095/396] drm/vc4: txp: Remove vc4_dev txp pointer There's no user for that pointer so let's just get rid of it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-50-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 1 - drivers/gpu/drm/vc4/vc4_txp.c | 6 ------ 2 files changed, 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 835d286c2802..0eb5f8a669fe 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -85,7 +85,6 @@ struct vc4_dev { struct vc4_hvs *hvs; struct vc4_v3d *v3d; struct vc4_vec *vec; - struct vc4_txp *txp; struct vc4_hang_state *hang_state; diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 448d48e7e99f..483a03a07ed2 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -469,7 +469,6 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_crtc *vc4_crtc; struct vc4_txp *txp; struct drm_crtc *crtc; @@ -523,7 +522,6 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) return ret; dev_set_drvdata(dev, txp); - vc4->txp = txp; vc4_debugfs_add_regset32(drm, "txp_regs", &txp->regset); @@ -533,13 +531,9 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) static void vc4_txp_unbind(struct device *dev, struct device *master, void *data) { - struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_txp *txp = dev_get_drvdata(dev); vc4_txp_connector_destroy(&txp->connector.base); - - vc4->txp = NULL; } static const struct component_ops vc4_txp_ops = { From 260ad78e9df95aa6154d85e7a9247aef28664854 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:20 +0200 Subject: [PATCH 096/396] drm/vc4: txp: Remove duplicate regset There's already a regset in the vc4_crtc structure so there's no need to duplicate it in vc4_txp. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-51-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_txp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 483a03a07ed2..19e37924ce77 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -155,7 +155,6 @@ struct vc4_txp { struct drm_writeback_connector connector; void __iomem *regs; - struct debugfs_regset32 regset; }; static inline struct vc4_txp *encoder_to_vc4_txp(struct drm_encoder *encoder) @@ -494,9 +493,9 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) txp->regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(txp->regs)) return PTR_ERR(txp->regs); - txp->regset.base = txp->regs; - txp->regset.regs = txp_regs; - txp->regset.nregs = ARRAY_SIZE(txp_regs); + vc4_crtc->regset.base = txp->regs; + vc4_crtc->regset.regs = txp_regs; + vc4_crtc->regset.nregs = ARRAY_SIZE(txp_regs); drm_connector_helper_add(&txp->connector.base, &vc4_txp_connector_helper_funcs); @@ -523,7 +522,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, txp); - vc4_debugfs_add_regset32(drm, "txp_regs", &txp->regset); + vc4_debugfs_add_regset32(drm, "txp_regs", &vc4_crtc->regset); return 0; } From b0da34c7970f6a5f156fd8036fbb83c999903628 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:21 +0200 Subject: [PATCH 097/396] drm/vc4: txp: Switch to drmm_kzalloc Our internal structure that stores the DRM entities structure is allocated through a device-managed kzalloc. This means that this will eventually be freed whenever the device is removed. In our case, the most likely source of removal is that the main device is going to be unbound, and component_unbind_all() is being run. However, it occurs while the DRM device is still registered, which will create dangling pointers, eventually resulting in use-after-free. Switch to a DRM-managed allocation to keep our structure until the DRM driver doesn't need it anymore. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-52-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_txp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 19e37924ce77..160f9d0ec6f0 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -478,7 +478,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) if (irq < 0) return irq; - txp = devm_kzalloc(dev, sizeof(*txp), GFP_KERNEL); + txp = drmm_kzalloc(drm, sizeof(*txp), GFP_KERNEL); if (!txp) return -ENOMEM; vc4_crtc = &txp->base; From d67210bbe5f3ec53fa6a46fbaad87d7a65ab544c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:22 +0200 Subject: [PATCH 098/396] drm/vc4: txp: Remove call to drm_connector_unregister() drm_connector_unregister() is only to be used for connectors that have been registered through drm_connector_register() after drm_dev_register() has been called. This is our case here so let's remove the call. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-53-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_txp.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 160f9d0ec6f0..7e5212bcf8e6 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -336,16 +336,10 @@ vc4_txp_connector_detect(struct drm_connector *connector, bool force) return connector_status_connected; } -static void vc4_txp_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - static const struct drm_connector_funcs vc4_txp_connector_funcs = { .detect = vc4_txp_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_txp_connector_destroy, + .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, @@ -532,7 +526,7 @@ static void vc4_txp_unbind(struct device *dev, struct device *master, { struct vc4_txp *txp = dev_get_drvdata(dev); - vc4_txp_connector_destroy(&txp->connector.base); + drm_connector_cleanup(&txp->connector.base); } static const struct component_ops vc4_txp_ops = { From b7345c9799da578c150fde3072446e4049c39c41 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:23 +0200 Subject: [PATCH 099/396] drm/vc4: txp: Protect device resources Our current code now mixes some resources whose lifetime are tied to the device (clocks, IO mappings, etc.) and some that are tied to the DRM device (encoder, bridge). The device one will be freed at unbind time, but the DRM one will only be freed when the last user of the DRM device closes its file handle. So we end up with a time window during which we can call the encoder hooks, but we don't have access to the underlying resources and device. Let's protect all those sections with drm_dev_enter() and drm_dev_exit() so that we bail out if we are during that window. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-54-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_txp.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 7e5212bcf8e6..f6f61cf5f3f7 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -15,6 +15,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_edid.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> @@ -275,6 +276,7 @@ static int vc4_txp_connector_atomic_check(struct drm_connector *conn, static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, struct drm_atomic_state *state) { + struct drm_device *drm = conn->dev; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, conn); struct vc4_txp *txp = connector_to_vc4_txp(conn); @@ -282,6 +284,7 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, struct drm_display_mode *mode; struct drm_framebuffer *fb; u32 ctrl; + int idx; int i; if (WARN_ON(!conn_state->writeback_job)) @@ -311,6 +314,9 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, */ ctrl |= TXP_ALPHA_INVERT; + if (!drm_dev_enter(drm, &idx)) + return; + gem = drm_fb_cma_get_gem_obj(fb, 0); TXP_WRITE(TXP_DST_PTR, gem->paddr + fb->offsets[0]); TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); @@ -321,6 +327,8 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, TXP_WRITE(TXP_DST_CTRL, ctrl); drm_writeback_queue_job(&txp->connector, conn_state); + + drm_dev_exit(idx); } static const struct drm_connector_helper_funcs vc4_txp_connector_helper_funcs = { @@ -347,7 +355,12 @@ static const struct drm_connector_funcs vc4_txp_connector_funcs = { static void vc4_txp_encoder_disable(struct drm_encoder *encoder) { + struct drm_device *drm = encoder->dev; struct vc4_txp *txp = encoder_to_vc4_txp(encoder); + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; if (TXP_READ(TXP_DST_CTRL) & TXP_BUSY) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); @@ -362,6 +375,8 @@ static void vc4_txp_encoder_disable(struct drm_encoder *encoder) } TXP_WRITE(TXP_DST_CTRL, TXP_POWERDOWN); + + drm_dev_exit(idx); } static const struct drm_encoder_helper_funcs vc4_txp_encoder_helper_funcs = { @@ -445,6 +460,16 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data) struct vc4_txp *txp = data; struct vc4_crtc *vc4_crtc = &txp->base; + /* + * We don't need to protect the register access using + * drm_dev_enter() there because the interrupt handler lifetime + * is tied to the device itself, and not to the DRM device. + * + * So when the device will be gone, one of the first thing we + * will be doing will be to unregister the interrupt handler, + * and then unregister the DRM device. drm_dev_enter() would + * thus always succeed if we are here. + */ TXP_WRITE(TXP_DST_CTRL, TXP_READ(TXP_DST_CTRL) & ~TXP_EI); vc4_crtc_handle_vblank(vc4_crtc); drm_writeback_signal_completion(&txp->connector, 0); From a0883e4df276b3ac9532d4de6fa7e1186cfa161c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:24 +0200 Subject: [PATCH 100/396] drm/vc4: vec: Remove vc4_dev vec pointer There's no user for that pointer so let's just get rid of it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-55-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 1 - drivers/gpu/drm/vc4/vc4_vec.c | 7 ------- 2 files changed, 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 0eb5f8a669fe..b7ccdc2b09de 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -84,7 +84,6 @@ struct vc4_dev { struct vc4_hvs *hvs; struct vc4_v3d *v3d; - struct vc4_vec *vec; struct vc4_hang_state *hang_state; diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 11fc3d6f66b1..99fe40c8cf81 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -532,7 +532,6 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_vec *vec; struct vc4_vec_encoder *vc4_vec_encoder; int ret; @@ -585,8 +584,6 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, vec); - vc4->vec = vec; - vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset); return 0; @@ -601,15 +598,11 @@ err_destroy_encoder: static void vc4_vec_unbind(struct device *dev, struct device *master, void *data) { - struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_vec *vec = dev_get_drvdata(dev); vc4_vec_connector_destroy(vec->connector); drm_encoder_cleanup(vec->encoder); pm_runtime_disable(dev); - - vc4->vec = NULL; } static const struct component_ops vc4_vec_ops = { From 9780315b068204bae921512154fefe84d321079e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:25 +0200 Subject: [PATCH 101/396] drm/vc4: vec: Embed DRM structures into the private structure The VC4 VEC driver private structure contains only a pointer to the encoder and connector it implements. This makes the overall structure somewhat inconsistent with the rest of the driver, and complicates its initialisation without any apparent gain. Let's embed the drm_encoder structure (through the vc4_encoder one) and drm_connector into struct vc4_vec to fix both issues. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-56-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 83 +++++++++-------------------------- 1 file changed, 21 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 99fe40c8cf81..2c96d5adcf49 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -160,12 +160,12 @@ struct vc4_vec_variant { /* General VEC hardware state. */ struct vc4_vec { + struct vc4_encoder encoder; + struct drm_connector connector; + struct platform_device *pdev; const struct vc4_vec_variant *variant; - struct drm_encoder *encoder; - struct drm_connector *connector; - void __iomem *regs; struct clk *clock; @@ -178,30 +178,12 @@ struct vc4_vec { #define VEC_READ(offset) readl(vec->regs + (offset)) #define VEC_WRITE(offset, val) writel(val, vec->regs + (offset)) -/* VC4 VEC encoder KMS struct */ -struct vc4_vec_encoder { - struct vc4_encoder base; - struct vc4_vec *vec; -}; - -static inline struct vc4_vec_encoder * -to_vc4_vec_encoder(struct drm_encoder *encoder) +static inline struct vc4_vec * +encoder_to_vc4_vec(struct drm_encoder *encoder) { - return container_of(encoder, struct vc4_vec_encoder, base.base); + return container_of(encoder, struct vc4_vec, encoder.base); } -/* VC4 VEC connector KMS struct */ -struct vc4_vec_connector { - struct drm_connector base; - struct vc4_vec *vec; - - /* Since the connector is attached to just the one encoder, - * this is the reference to it so we can do the best_encoder() - * hook. - */ - struct drm_encoder *encoder; -}; - enum vc4_vec_tv_mode_id { VC4_VEC_TV_MODE_NTSC, VC4_VEC_TV_MODE_NTSC_J, @@ -343,22 +325,12 @@ static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = .get_modes = vc4_vec_connector_get_modes, }; -static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, - struct vc4_vec *vec) +static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) { - struct drm_connector *connector = NULL; - struct vc4_vec_connector *vec_connector; + struct drm_connector *connector = &vec->connector; - vec_connector = devm_kzalloc(dev->dev, sizeof(*vec_connector), - GFP_KERNEL); - if (!vec_connector) - return ERR_PTR(-ENOMEM); - - connector = &vec_connector->base; connector->interlace_allowed = true; - vec_connector->encoder = vec->encoder; - vec_connector->vec = vec; drm_connector_init(dev, connector, &vc4_vec_connector_funcs, DRM_MODE_CONNECTOR_Composite); @@ -369,15 +341,14 @@ static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, VC4_VEC_TV_MODE_NTSC); vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC]; - drm_connector_attach_encoder(connector, vec->encoder); + drm_connector_attach_encoder(connector, &vec->encoder.base); - return connector; + return 0; } static void vc4_vec_encoder_disable(struct drm_encoder *encoder) { - struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); - struct vc4_vec *vec = vc4_vec_encoder->vec; + struct vc4_vec *vec = encoder_to_vc4_vec(encoder); int ret; VEC_WRITE(VEC_CFG, 0); @@ -398,8 +369,7 @@ static void vc4_vec_encoder_disable(struct drm_encoder *encoder) static void vc4_vec_encoder_enable(struct drm_encoder *encoder) { - struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); - struct vc4_vec *vec = vc4_vec_encoder->vec; + struct vc4_vec *vec = encoder_to_vc4_vec(encoder); int ret; ret = pm_runtime_get_sync(&vec->pdev->dev); @@ -474,8 +444,7 @@ static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { - struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); - struct vc4_vec *vec = vc4_vec_encoder->vec; + struct vc4_vec *vec = encoder_to_vc4_vec(encoder); vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; } @@ -533,7 +502,6 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); struct vc4_vec *vec; - struct vc4_vec_encoder *vc4_vec_encoder; int ret; ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names), @@ -545,14 +513,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) if (!vec) return -ENOMEM; - vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder), - GFP_KERNEL); - if (!vc4_vec_encoder) - return -ENOMEM; - vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC; - vc4_vec_encoder->vec = vec; - vec->encoder = &vc4_vec_encoder->base.base; - + vec->encoder.type = VC4_ENCODER_TYPE_VEC; vec->pdev = pdev; vec->variant = (const struct vc4_vec_variant *) of_device_get_match_data(dev); @@ -573,14 +534,12 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(dev); - drm_simple_encoder_init(drm, vec->encoder, DRM_MODE_ENCODER_TVDAC); - drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs); + drm_simple_encoder_init(drm, &vec->encoder.base, DRM_MODE_ENCODER_TVDAC); + drm_encoder_helper_add(&vec->encoder.base, &vc4_vec_encoder_helper_funcs); - vec->connector = vc4_vec_connector_init(drm, vec); - if (IS_ERR(vec->connector)) { - ret = PTR_ERR(vec->connector); + ret = vc4_vec_connector_init(drm, vec); + if (ret) goto err_destroy_encoder; - } dev_set_drvdata(dev, vec); @@ -589,7 +548,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) return 0; err_destroy_encoder: - drm_encoder_cleanup(vec->encoder); + drm_encoder_cleanup(&vec->encoder.base); pm_runtime_disable(dev); return ret; @@ -600,8 +559,8 @@ static void vc4_vec_unbind(struct device *dev, struct device *master, { struct vc4_vec *vec = dev_get_drvdata(dev); - vc4_vec_connector_destroy(vec->connector); - drm_encoder_cleanup(vec->encoder); + vc4_vec_connector_destroy(&vec->connector); + drm_encoder_cleanup(&vec->encoder.base); pm_runtime_disable(dev); } From fe7289e2184485c5dc51cc49a94e442d14d08255 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:26 +0200 Subject: [PATCH 102/396] drm/vc4: vec: Switch to drmm_kzalloc Our internal structure that stores the DRM entities structure is allocated through a device-managed kzalloc. This means that this will eventually be freed whenever the device is removed. In our case, the most likely source of removal is that the main device is going to be unbound, and component_unbind_all() is being run. However, it occurs while the DRM device is still registered, which will create dangling pointers, eventually resulting in use-after-free. Switch to a DRM-managed allocation to keep our structure until the DRM driver doesn't need it anymore. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-57-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 2c96d5adcf49..a051b25337c0 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -509,7 +509,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; - vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL); + vec = drmm_kzalloc(drm, sizeof(*vec), GFP_KERNEL); if (!vec) return -ENOMEM; From cd2444a7953972ed495b8c0e8f6202d6ad11fb0d Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:27 +0200 Subject: [PATCH 103/396] drm/vc4: vec: Remove call to drm_connector_unregister() drm_connector_unregister() is only to be used for connectors that have been registered through drm_connector_register() after drm_dev_register() has been called. This is our case here so let's remove the call. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-58-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index a051b25337c0..2e9dc09fc6f0 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -289,12 +289,6 @@ vc4_vec_connector_detect(struct drm_connector *connector, bool force) return connector_status_unknown; } -static void vc4_vec_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - static int vc4_vec_connector_get_modes(struct drm_connector *connector) { struct drm_connector_state *state = connector->state; @@ -315,7 +309,7 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector) static const struct drm_connector_funcs vc4_vec_connector_funcs = { .detect = vc4_vec_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_vec_connector_destroy, + .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, @@ -559,7 +553,7 @@ static void vc4_vec_unbind(struct device *dev, struct device *master, { struct vc4_vec *vec = dev_get_drvdata(dev); - vc4_vec_connector_destroy(&vec->connector); + drm_connector_cleanup(&vec->connector); drm_encoder_cleanup(&vec->encoder.base); pm_runtime_disable(dev); } From c62f432f2ed97305f96d393c5e3756ca1cd3c1de Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:28 +0200 Subject: [PATCH 104/396] drm/vc4: vec: Switch to DRM-managed encoder initialization The current code will call drm_encoder_cleanup() when the device is unbound. However, by then, there might still be some references held to that encoder, including by the userspace that might still have the DRM device open. Let's switch to a DRM-managed initialization to clean up after ourselves only once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-59-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 2e9dc09fc6f0..518b66bcc0b5 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -528,12 +528,18 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(dev); - drm_simple_encoder_init(drm, &vec->encoder.base, DRM_MODE_ENCODER_TVDAC); + ret = drmm_encoder_init(drm, &vec->encoder.base, + NULL, + DRM_MODE_ENCODER_TVDAC, + NULL); + if (ret) + goto err_put_runtime_pm; + drm_encoder_helper_add(&vec->encoder.base, &vc4_vec_encoder_helper_funcs); ret = vc4_vec_connector_init(drm, vec); if (ret) - goto err_destroy_encoder; + goto err_put_runtime_pm; dev_set_drvdata(dev, vec); @@ -541,8 +547,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) return 0; -err_destroy_encoder: - drm_encoder_cleanup(&vec->encoder.base); +err_put_runtime_pm: pm_runtime_disable(dev); return ret; @@ -554,7 +559,6 @@ static void vc4_vec_unbind(struct device *dev, struct device *master, struct vc4_vec *vec = dev_get_drvdata(dev); drm_connector_cleanup(&vec->connector); - drm_encoder_cleanup(&vec->encoder.base); pm_runtime_disable(dev); } From 881f6d945b34e5604003ba1cc85c9dfbb7e31af2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:29 +0200 Subject: [PATCH 105/396] drm/vc4: vec: Switch to DRM-managed connector initialization The current code will call drm_connector_unregister() and drm_connector_cleanup() when the device is unbound. However, by then, there might still be some references held to that connector, including by the userspace that might still have the DRM device open. Let's switch to a DRM-managed initialization to clean up after ourselves only once the DRM device has been last closed. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-60-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 518b66bcc0b5..4b843b18c006 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -309,7 +309,6 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector) static const struct drm_connector_funcs vc4_vec_connector_funcs = { .detect = vc4_vec_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, @@ -322,12 +321,15 @@ static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) { struct drm_connector *connector = &vec->connector; + int ret; connector->interlace_allowed = true; + ret = drmm_connector_init(dev, connector, &vc4_vec_connector_funcs, + DRM_MODE_CONNECTOR_Composite, NULL); + if (ret) + return ret; - drm_connector_init(dev, connector, &vc4_vec_connector_funcs, - DRM_MODE_CONNECTOR_Composite); drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs); drm_object_attach_property(&connector->base, @@ -556,9 +558,6 @@ err_put_runtime_pm: static void vc4_vec_unbind(struct device *dev, struct device *master, void *data) { - struct vc4_vec *vec = dev_get_drvdata(dev); - - drm_connector_cleanup(&vec->connector); pm_runtime_disable(dev); } From f0601ef8631ceeab10c7af69b248fc106e0ecf09 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:30 +0200 Subject: [PATCH 106/396] drm/vc4: vec: Protect device resources after removal Whenever the device and driver are unbound, the main device and all the subdevices will be removed by calling their unbind() method. However, the DRM device itself will only be freed when the last user will have closed it. It means that there is a time window where the device and its resources aren't there anymore, but the userspace can still call into our driver. Fortunately, the DRM framework provides the drm_dev_enter() and drm_dev_exit() functions to make sure our underlying device is still there for the section protected by those calls. Let's add them to the VEC driver. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-61-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 67 +++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 4b843b18c006..df6adef96050 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -14,6 +14,7 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_edid.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> @@ -225,14 +226,30 @@ static const struct debugfs_reg32 vec_regs[] = { static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec) { + struct drm_device *drm = vec->connector.dev; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; + VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN); VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); + + drm_dev_exit(idx); } static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec) { + struct drm_device *drm = vec->connector.dev; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; + VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD); VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); + + drm_dev_exit(idx); } static const struct drm_display_mode ntsc_mode = { @@ -244,17 +261,33 @@ static const struct drm_display_mode ntsc_mode = { static void vc4_vec_pal_mode_set(struct vc4_vec *vec) { + struct drm_device *drm = vec->connector.dev; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; + VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); + + drm_dev_exit(idx); } static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec) { + struct drm_device *drm = vec->connector.dev; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; + VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ); VEC_WRITE(VEC_FREQ3_2, 0x223b); VEC_WRITE(VEC_FREQ1_0, 0x61d1); + + drm_dev_exit(idx); } static const struct drm_display_mode pal_mode = { @@ -344,8 +377,12 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) static void vc4_vec_encoder_disable(struct drm_encoder *encoder) { + struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); - int ret; + int idx, ret; + + if (!drm_dev_enter(drm, &idx)) + return; VEC_WRITE(VEC_CFG, 0); VEC_WRITE(VEC_DAC_MISC, @@ -359,19 +396,29 @@ static void vc4_vec_encoder_disable(struct drm_encoder *encoder) ret = pm_runtime_put(&vec->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to release power domain: %d\n", ret); - return; + goto err_dev_exit; } + + drm_dev_exit(idx); + return; + +err_dev_exit: + drm_dev_exit(idx); } static void vc4_vec_encoder_enable(struct drm_encoder *encoder) { + struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); - int ret; + int idx, ret; + + if (!drm_dev_enter(drm, &idx)) + return; ret = pm_runtime_get_sync(&vec->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to retain power domain: %d\n", ret); - return; + goto err_dev_exit; } /* @@ -384,13 +431,13 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) ret = clk_set_rate(vec->clock, 108000000); if (ret) { DRM_ERROR("Failed to set clock rate: %d\n", ret); - return; + goto err_put_runtime_pm; } ret = clk_prepare_enable(vec->clock); if (ret) { DRM_ERROR("Failed to turn on core clock: %d\n", ret); - return; + goto err_put_runtime_pm; } /* Reset the different blocks */ @@ -426,6 +473,14 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) VEC_WRITE(VEC_DAC_MISC, VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N); VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN); + + drm_dev_exit(idx); + return; + +err_put_runtime_pm: + pm_runtime_put(&vec->pdev->dev); +err_dev_exit: + drm_dev_exit(idx); } From 4e06fd9c7c8a2815c63ff132fd392d76e42436e9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:31 +0200 Subject: [PATCH 107/396] drm/vc4: vec: Switch to devm_pm_runtime_enable devm_pm_runtime_enable() simplifies the driver a bit since it will call pm_runtime_disable() automatically through a device-managed action. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-62-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index df6adef96050..d356ffa52866 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -583,42 +583,32 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) return ret; } - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; ret = drmm_encoder_init(drm, &vec->encoder.base, NULL, DRM_MODE_ENCODER_TVDAC, NULL); if (ret) - goto err_put_runtime_pm; + return ret; drm_encoder_helper_add(&vec->encoder.base, &vc4_vec_encoder_helper_funcs); ret = vc4_vec_connector_init(drm, vec); if (ret) - goto err_put_runtime_pm; + return ret; dev_set_drvdata(dev, vec); vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset); return 0; - -err_put_runtime_pm: - pm_runtime_disable(dev); - - return ret; -} - -static void vc4_vec_unbind(struct device *dev, struct device *master, - void *data) -{ - pm_runtime_disable(dev); } static const struct component_ops vc4_vec_ops = { .bind = vc4_vec_bind, - .unbind = vc4_vec_unbind, }; static int vc4_vec_dev_probe(struct platform_device *pdev) From be919b89b28e0fa3c4eff39dd96350bc7803f194 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:32 +0200 Subject: [PATCH 108/396] drm/vc4: debugfs: Protect device resources Our current code now mixes some resources whose lifetime are tied to the device (clocks, IO mappings, etc.) and some that are tied to the DRM device (encoder, bridge). The device one will be freed at unbind time, but the DRM one will only be freed when the last user of the DRM device closes its file handle. So we end up with a time window during which we can call the encoder hooks, but we don't have access to the underlying resources and device. Let's protect all those sections with drm_dev_enter() and drm_dev_exit() so that we bail out if we are during that window. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-63-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_debugfs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index ba2d8ea562af..d6350a8ca048 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -3,6 +3,8 @@ * Copyright © 2014 Broadcom */ +#include <drm/drm_drv.h> + #include <linux/seq_file.h> #include <linux/circ_buf.h> #include <linux/ctype.h> @@ -41,11 +43,18 @@ vc4_debugfs_init(struct drm_minor *minor) static int vc4_debugfs_regset32(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_device *drm = node->minor->dev; struct debugfs_regset32 *regset = node->info_ent->data; struct drm_printer p = drm_seq_file_printer(m); + int idx; + + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; drm_print_regset32(&p, regset); + drm_dev_exit(idx); + return 0; } From fe3b0f784cc8bb208fada872c13e6bd694bb1669 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:33 +0200 Subject: [PATCH 109/396] drm/vc4: debugfs: Return an error on failure vc4_debugfs_add_file() can fail, so let's propagate its error code instead of silencing it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-64-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_debugfs.c | 20 +++++++++++--------- drivers/gpu/drm/vc4/vc4_drv.h | 30 ++++++++++++++++-------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index d6350a8ca048..b857fb9c94bc 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -67,10 +67,10 @@ static int vc4_debugfs_regset32(struct seq_file *m, void *unused) * track the request and delay it to be called on each minor during * vc4_debugfs_init(). */ -void vc4_debugfs_add_file(struct drm_device *dev, - const char *name, - int (*show)(struct seq_file*, void*), - void *data) +int vc4_debugfs_add_file(struct drm_device *dev, + const char *name, + int (*show)(struct seq_file*, void*), + void *data) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -78,18 +78,20 @@ void vc4_debugfs_add_file(struct drm_device *dev, devm_kzalloc(dev->dev, sizeof(*entry), GFP_KERNEL); if (!entry) - return; + return -ENOMEM; entry->info.name = name; entry->info.show = show; entry->info.data = data; list_add(&entry->link, &vc4->debugfs_list); + + return 0; } -void vc4_debugfs_add_regset32(struct drm_device *drm, - const char *name, - struct debugfs_regset32 *regset) +int vc4_debugfs_add_regset32(struct drm_device *drm, + const char *name, + struct debugfs_regset32 *regset) { - vc4_debugfs_add_file(drm, name, vc4_debugfs_regset32, regset); + return vc4_debugfs_add_file(drm, name, vc4_debugfs_regset32, regset); } diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index b7ccdc2b09de..5d857816426b 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -866,25 +866,27 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state, /* vc4_debugfs.c */ void vc4_debugfs_init(struct drm_minor *minor); #ifdef CONFIG_DEBUG_FS -void vc4_debugfs_add_file(struct drm_device *drm, - const char *filename, - int (*show)(struct seq_file*, void*), - void *data); -void vc4_debugfs_add_regset32(struct drm_device *drm, - const char *filename, - struct debugfs_regset32 *regset); +int vc4_debugfs_add_file(struct drm_device *drm, + const char *filename, + int (*show)(struct seq_file*, void*), + void *data); +int vc4_debugfs_add_regset32(struct drm_device *drm, + const char *filename, + struct debugfs_regset32 *regset); #else -static inline void vc4_debugfs_add_file(struct drm_device *drm, - const char *filename, - int (*show)(struct seq_file*, void*), - void *data) +static inline int vc4_debugfs_add_file(struct drm_device *drm, + const char *filename, + int (*show)(struct seq_file*, void*), + void *data) { + return 0; } -static inline void vc4_debugfs_add_regset32(struct drm_device *drm, - const char *filename, - struct debugfs_regset32 *regset) +static inline int vc4_debugfs_add_regset32(struct drm_device *drm, + const char *filename, + struct debugfs_regset32 *regset) { + return 0; } #endif From 445b287e18ca374b5498e0f7cecb6c5f673c4edb Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:34 +0200 Subject: [PATCH 110/396] drm/vc4: debugfs: Simplify debugfs registration The vc4 has a custom API to allow components to register a debugfs file before the DRM driver has been registered and the debugfs_init hook has been called. However, the .late_register hook allows to have the debugfs file creation deferred after that time already. Let's remove our custom code to only register later our debugfs entries as part of either debugfs_init or after it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-65-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_bo.c | 20 ++++++++++-- drivers/gpu/drm/vc4/vc4_crtc.c | 19 ++++++++++-- drivers/gpu/drm/vc4/vc4_debugfs.c | 51 +++++++++++-------------------- drivers/gpu/drm/vc4/vc4_dpi.c | 21 +++++++++++-- drivers/gpu/drm/vc4/vc4_drv.h | 12 +++++--- drivers/gpu/drm/vc4/vc4_dsi.c | 22 +++++++++++-- drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++--- drivers/gpu/drm/vc4/vc4_hvs.c | 39 +++++++++++++++++++---- drivers/gpu/drm/vc4/vc4_txp.c | 3 +- drivers/gpu/drm/vc4/vc4_v3d.c | 25 +++++++++++++-- drivers/gpu/drm/vc4/vc4_vec.c | 22 +++++++++++-- 11 files changed, 191 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 0846d56f74f2..9706fec47bcd 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -984,6 +984,23 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data, return 0; } +int vc4_bo_debugfs_init(struct drm_minor *minor) +{ + struct drm_device *drm = minor->dev; + struct vc4_dev *vc4 = to_vc4_dev(drm); + int ret; + + if (!vc4->v3d) + return -ENODEV; + + ret = vc4_debugfs_add_file(minor, "bo_stats", + vc4_bo_stats_debugfs, NULL); + if (ret) + return ret; + + return 0; +} + static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused); int vc4_bo_cache_init(struct drm_device *dev) { @@ -1008,9 +1025,6 @@ int vc4_bo_cache_init(struct drm_device *dev) vc4->bo_labels[i].name = bo_type_names[i]; mutex_init(&vc4->bo_lock); - - vc4_debugfs_add_file(dev, "bo_stats", vc4_bo_stats_debugfs, NULL); - INIT_LIST_HEAD(&vc4->bo_cache.time_list); INIT_WORK(&vc4->bo_cache.time_work, vc4_bo_cache_time_work); diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 3768a2a57ca9..d3efa7e5b5ed 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1052,6 +1052,21 @@ void vc4_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base); } +int vc4_crtc_late_register(struct drm_crtc *crtc) +{ + struct drm_device *drm = crtc->dev; + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); + int ret; + + ret = vc4_debugfs_add_regset32(drm->primary, crtc_data->debugfs_name, + &vc4_crtc->regset); + if (ret) + return ret; + + return 0; +} + static const struct drm_crtc_funcs vc4_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .page_flip = vc4_page_flip, @@ -1064,6 +1079,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { .enable_vblank = vc4_enable_vblank, .disable_vblank = vc4_disable_vblank, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, + .late_register = vc4_crtc_late_register, }; static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { @@ -1318,9 +1334,6 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) platform_set_drvdata(pdev, vc4_crtc); - vc4_debugfs_add_regset32(drm, pv_data->base.debugfs_name, - &vc4_crtc->regset); - return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index b857fb9c94bc..19cda4f91a82 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -14,11 +14,6 @@ #include "vc4_drv.h" #include "vc4_regs.h" -struct vc4_debugfs_info_entry { - struct list_head link; - struct drm_info_list info; -}; - /* * Called at drm_dev_register() time on each of the minors registered * by the DRM device, to attach the debugfs files. @@ -27,16 +22,13 @@ void vc4_debugfs_init(struct drm_minor *minor) { struct vc4_dev *vc4 = to_vc4_dev(minor->dev); - struct vc4_debugfs_info_entry *entry; + struct drm_device *drm = &vc4->base; - if (!of_device_is_compatible(vc4->hvs->pdev->dev.of_node, - "brcm,bcm2711-vc5")) - debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, - minor->debugfs_root, &vc4->load_tracker_enabled); + drm_WARN_ON(drm, vc4_hvs_debugfs_init(minor)); - list_for_each_entry(entry, &vc4->debugfs_list, link) { - drm_debugfs_create_files(&entry->info, 1, - minor->debugfs_root, minor); + if (vc4->v3d) { + drm_WARN_ON(drm, vc4_bo_debugfs_init(minor)); + drm_WARN_ON(drm, vc4_v3d_debugfs_init(minor)); } } @@ -58,40 +50,31 @@ static int vc4_debugfs_regset32(struct seq_file *m, void *unused) return 0; } -/* - * Registers a debugfs file with a callback function for a vc4 component. - * - * This is like drm_debugfs_create_files(), but that can only be - * called a given DRM minor, while the various VC4 components want to - * register their debugfs files during the component bind process. We - * track the request and delay it to be called on each minor during - * vc4_debugfs_init(). - */ -int vc4_debugfs_add_file(struct drm_device *dev, +int vc4_debugfs_add_file(struct drm_minor *minor, const char *name, int (*show)(struct seq_file*, void*), void *data) { - struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_device *dev = minor->dev; + struct dentry *root = minor->debugfs_root; + struct drm_info_list *file; - struct vc4_debugfs_info_entry *entry = - devm_kzalloc(dev->dev, sizeof(*entry), GFP_KERNEL); - - if (!entry) + file = drmm_kzalloc(dev, sizeof(*file), GFP_KERNEL); + if (!file) return -ENOMEM; - entry->info.name = name; - entry->info.show = show; - entry->info.data = data; + file->name = name; + file->show = show; + file->data = data; - list_add(&entry->link, &vc4->debugfs_list); + drm_debugfs_create_files(file, 1, root, minor); return 0; } -int vc4_debugfs_add_regset32(struct drm_device *drm, +int vc4_debugfs_add_regset32(struct drm_minor *minor, const char *name, struct debugfs_regset32 *regset) { - return vc4_debugfs_add_file(drm, name, vc4_debugfs_regset32, regset); + return vc4_debugfs_add_file(minor, name, vc4_debugfs_regset32, regset); } diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 7286a3333538..1f8f44b7b5a5 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -244,6 +244,23 @@ static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = { .mode_valid = vc4_dpi_encoder_mode_valid, }; +static int vc4_dpi_late_register(struct drm_encoder *encoder) +{ + struct drm_device *drm = encoder->dev; + struct vc4_dpi *dpi = to_vc4_dpi(encoder); + int ret; + + ret = vc4_debugfs_add_regset32(drm->primary, "dpi_regs", &dpi->regset); + if (ret) + return ret; + + return 0; +} + +static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = { + .late_register = vc4_dpi_late_register, +}; + static const struct of_device_id vc4_dpi_dt_match[] = { { .compatible = "brcm,bcm2835-dpi", .data = NULL }, {} @@ -332,7 +349,7 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) return ret; ret = drmm_encoder_init(drm, &dpi->encoder.base, - NULL, + &vc4_dpi_encoder_funcs, DRM_MODE_ENCODER_DPI, NULL); if (ret) @@ -346,8 +363,6 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, dpi); - vc4_debugfs_add_regset32(drm, "dpi_regs", &dpi->regset); - return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 5d857816426b..1649350b9efd 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -841,6 +841,7 @@ int vc4_bo_inc_usecnt(struct vc4_bo *bo); void vc4_bo_dec_usecnt(struct vc4_bo *bo); void vc4_bo_add_to_purgeable_pool(struct vc4_bo *bo); void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo); +int vc4_bo_debugfs_init(struct drm_minor *minor); /* vc4_crtc.c */ extern struct platform_driver vc4_crtc_driver; @@ -859,6 +860,7 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc, void vc4_crtc_reset(struct drm_crtc *crtc); void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); void vc4_crtc_send_vblank(struct drm_crtc *crtc); +int vc4_crtc_late_register(struct drm_crtc *crtc); void vc4_crtc_get_margins(struct drm_crtc_state *state, unsigned int *left, unsigned int *right, unsigned int *top, unsigned int *bottom); @@ -866,15 +868,15 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state, /* vc4_debugfs.c */ void vc4_debugfs_init(struct drm_minor *minor); #ifdef CONFIG_DEBUG_FS -int vc4_debugfs_add_file(struct drm_device *drm, +int vc4_debugfs_add_file(struct drm_minor *minor, const char *filename, int (*show)(struct seq_file*, void*), void *data); -int vc4_debugfs_add_regset32(struct drm_device *drm, +int vc4_debugfs_add_regset32(struct drm_minor *minor, const char *filename, struct debugfs_regset32 *regset); #else -static inline int vc4_debugfs_add_file(struct drm_device *drm, +static inline int vc4_debugfs_add_file(struct drm_minor *minor, const char *filename, int (*show)(struct seq_file*, void*), void *data) @@ -882,7 +884,7 @@ static inline int vc4_debugfs_add_file(struct drm_device *drm, return 0; } -static inline int vc4_debugfs_add_regset32(struct drm_device *drm, +static inline int vc4_debugfs_add_regset32(struct drm_minor *minor, const char *filename, struct debugfs_regset32 *regset) { @@ -952,6 +954,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state) void vc4_hvs_dump_state(struct vc4_hvs *hvs); void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel); void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel); +int vc4_hvs_debugfs_init(struct drm_minor *minor); /* vc4_kms.c */ int vc4_kms_load(struct drm_device *dev); @@ -974,6 +977,7 @@ int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used); void vc4_v3d_bin_bo_put(struct vc4_dev *vc4); int vc4_v3d_pm_get(struct vc4_dev *vc4); void vc4_v3d_pm_put(struct vc4_dev *vc4); +int vc4_v3d_debugfs_init(struct drm_minor *minor); /* vc4_validate.c */ int diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 52c3215fef49..878e05d79e81 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1372,6 +1372,24 @@ static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = { .mode_fixup = vc4_dsi_encoder_mode_fixup, }; +static int vc4_dsi_late_register(struct drm_encoder *encoder) +{ + struct drm_device *drm = encoder->dev; + struct vc4_dsi *dsi = to_vc4_dsi(encoder); + int ret; + + ret = vc4_debugfs_add_regset32(drm->primary, dsi->variant->debugfs_name, + &dsi->regset); + if (ret) + return ret; + + return 0; +} + +static const struct drm_encoder_funcs vc4_dsi_encoder_funcs = { + .late_register = vc4_dsi_late_register, +}; + static const struct vc4_dsi_variant bcm2711_dsi1_variant = { .port = 1, .debugfs_name = "dsi1_regs", @@ -1721,7 +1739,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) return ret; ret = drmm_encoder_init(drm, encoder, - NULL, + &vc4_dsi_encoder_funcs, DRM_MODE_ENCODER_DSI, NULL); if (ret) @@ -1743,8 +1761,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) */ list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); - vc4_debugfs_add_regset32(drm, dsi->variant->debugfs_name, &dsi->regset); - return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 166d22d62d99..4acc865576f0 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1839,6 +1839,26 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { .mode_valid = vc4_hdmi_encoder_mode_valid, }; +static int vc4_hdmi_late_register(struct drm_encoder *encoder) +{ + struct drm_device *drm = encoder->dev; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; + int ret; + + ret = vc4_debugfs_add_file(drm->primary, variant->debugfs_name, + vc4_hdmi_debugfs_regs, + vc4_hdmi); + if (ret) + return ret; + + return 0; +} + +static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = { + .late_register = vc4_hdmi_late_register, +}; + static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) { int i; @@ -3335,7 +3355,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) } ret = drmm_encoder_init(drm, encoder, - NULL, + &vc4_hdmi_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); if (ret) @@ -3359,10 +3379,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_put_runtime_pm; - vc4_debugfs_add_file(drm, variant->debugfs_name, - vc4_hdmi_debugfs_regs, - vc4_hdmi); - pm_runtime_put_sync(dev); return 0; diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index a62f222255ce..9e823e0de197 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -733,6 +733,39 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data) return irqret; } +int vc4_hvs_debugfs_init(struct drm_minor *minor) +{ + struct drm_device *drm = minor->dev; + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_hvs *hvs = vc4->hvs; + int ret; + + if (!vc4->hvs) + return -ENODEV; + + if (!vc4->is_vc5) + debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, + minor->debugfs_root, + &vc4->load_tracker_enabled); + + ret = vc4_debugfs_add_file(minor, "hvs_dlists", + vc4_hvs_debugfs_dlist, NULL); + if (ret) + return ret; + + ret = vc4_debugfs_add_file(minor, "hvs_underrun", + vc4_hvs_debugfs_underrun, NULL); + if (ret) + return ret; + + ret = vc4_debugfs_add_regset32(minor, "hvs_regs", + &hvs->regset); + if (ret) + return ret; + + return 0; +} + static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -858,12 +891,6 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; - vc4_debugfs_add_regset32(drm, "hvs_regs", &hvs->regset); - vc4_debugfs_add_file(drm, "hvs_underrun", vc4_hvs_debugfs_underrun, - NULL); - vc4_debugfs_add_file(drm, "hvs_dlists", vc4_hvs_debugfs_dlist, - NULL); - return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index f6f61cf5f3f7..913e26dd62d4 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -398,6 +398,7 @@ static const struct drm_crtc_funcs vc4_txp_crtc_funcs = { .atomic_destroy_state = vc4_crtc_destroy_state, .enable_vblank = vc4_txp_enable_vblank, .disable_vblank = vc4_txp_disable_vblank, + .late_register = vc4_crtc_late_register, }; static int vc4_txp_atomic_check(struct drm_crtc *crtc, @@ -541,8 +542,6 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, txp); - vc4_debugfs_add_regset32(drm, "txp_regs", &vc4_crtc->regset); - return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index cc714dcfe1f2..e7990bed0a96 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -401,6 +401,28 @@ static int vc4_v3d_runtime_resume(struct device *dev) } #endif +int vc4_v3d_debugfs_init(struct drm_minor *minor) +{ + struct drm_device *drm = minor->dev; + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_v3d *v3d = vc4->v3d; + int ret; + + if (!vc4->v3d) + return -ENODEV; + + ret = vc4_debugfs_add_file(minor, "v3d_ident", + vc4_v3d_debugfs_ident, NULL); + if (ret) + return ret; + + ret = vc4_debugfs_add_regset32(minor, "v3d_regs", &v3d->regset); + if (ret) + return ret; + + return 0; +} + static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -477,9 +499,6 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ pm_runtime_enable(dev); - vc4_debugfs_add_file(drm, "v3d_ident", vc4_v3d_debugfs_ident, NULL); - vc4_debugfs_add_regset32(drm, "v3d_regs", &v3d->regset); - return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index d356ffa52866..4a788c1c9058 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -523,6 +523,24 @@ static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { .atomic_mode_set = vc4_vec_encoder_atomic_mode_set, }; +static int vc4_vec_late_register(struct drm_encoder *encoder) +{ + struct drm_device *drm = encoder->dev; + struct vc4_vec *vec = encoder_to_vc4_vec(encoder); + int ret; + + ret = vc4_debugfs_add_regset32(drm->primary, "vec_regs", + &vec->regset); + if (ret) + return ret; + + return 0; +} + +static const struct drm_encoder_funcs vc4_vec_encoder_funcs = { + .late_register = vc4_vec_late_register, +}; + static const struct vc4_vec_variant bcm2835_vec_variant = { .dac_config = VEC_DAC_CONFIG_DAC_CTRL(0xc) | VEC_DAC_CONFIG_DRIVER_CTRL(0xc) | @@ -588,7 +606,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) return ret; ret = drmm_encoder_init(drm, &vec->encoder.base, - NULL, + &vc4_vec_encoder_funcs, DRM_MODE_ENCODER_TVDAC, NULL); if (ret) @@ -602,8 +620,6 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, vec); - vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset); - return 0; } From 374146cad469102b683939009f18fa88f9b9b6c9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:35 +0200 Subject: [PATCH 111/396] drm/vc4: Switch to drmm_mutex_init mutex_init is supposed to be balanced by a call to mutex_destroy that we were never doing in the vc4 driver. Since a DRM-managed mutex_init variant has been introduced, let's just switch to it. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-66-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_bo.c | 15 +++++++++++++-- drivers/gpu/drm/vc4/vc4_drv.c | 4 +++- drivers/gpu/drm/vc4/vc4_gem.c | 10 ++++++++-- drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 9706fec47bcd..2ccf96b764db 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -394,6 +394,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) { struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_bo *bo; + int ret; if (WARN_ON_ONCE(vc4->is_vc5)) return ERR_PTR(-ENODEV); @@ -404,7 +405,11 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) bo->madv = VC4_MADV_WILLNEED; refcount_set(&bo->usecnt, 0); - mutex_init(&bo->madv_lock); + + ret = drmm_mutex_init(dev, &bo->madv_lock); + if (ret) + return ERR_PTR(ret); + mutex_lock(&vc4->bo_lock); bo->label = VC4_BO_TYPE_KERNEL; vc4->bo_labels[VC4_BO_TYPE_KERNEL].num_allocated++; @@ -1005,6 +1010,7 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused); int vc4_bo_cache_init(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; int i; if (WARN_ON_ONCE(vc4->is_vc5)) @@ -1024,7 +1030,12 @@ int vc4_bo_cache_init(struct drm_device *dev) for (i = 0; i < VC4_BO_TYPE_COUNT; i++) vc4->bo_labels[i].name = bo_type_names[i]; - mutex_init(&vc4->bo_lock); + ret = drmm_mutex_init(dev, &vc4->bo_lock); + if (ret) { + kfree(vc4->bo_labels); + return ret; + } + INIT_LIST_HEAD(&vc4->bo_cache.time_list); INIT_WORK(&vc4->bo_cache.time_work, vc4_bo_cache_time_work); diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 79a37d18aeb1..89975bdd607e 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -324,7 +324,9 @@ static int vc4_drm_bind(struct device *dev) INIT_LIST_HEAD(&vc4->debugfs_list); if (!is_vc5) { - mutex_init(&vc4->bin_bo_lock); + ret = drmm_mutex_init(drm, &vc4->bin_bo_lock); + if (ret) + return ret; ret = vc4_bo_cache_init(drm); if (ret) diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index fe10d9c3fff8..7acb43972e69 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -1308,6 +1308,7 @@ static void vc4_gem_destroy(struct drm_device *dev, void *unused); int vc4_gem_init(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; if (WARN_ON_ONCE(vc4->is_vc5)) return -ENODEV; @@ -1325,10 +1326,15 @@ int vc4_gem_init(struct drm_device *dev) INIT_WORK(&vc4->job_done_work, vc4_job_done_work); - mutex_init(&vc4->power_lock); + ret = drmm_mutex_init(dev, &vc4->power_lock); + if (ret) + return ret; INIT_LIST_HEAD(&vc4->purgeable.list); - mutex_init(&vc4->purgeable.lock); + + ret = drmm_mutex_init(dev, &vc4->purgeable.lock); + if (ret) + return ret; return drmm_add_action_or_reset(dev, vc4_gem_destroy, NULL); } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4acc865576f0..6f61a1b8a1a3 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -3270,7 +3270,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (!vc4_hdmi) return -ENOMEM; - mutex_init(&vc4_hdmi->mutex); + ret = drmm_mutex_init(drm, &vc4_hdmi->mutex); + if (ret) + return ret; + spin_lock_init(&vc4_hdmi->hw_lock); INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); From 57d68ee8f719efa05bcec64625a9898231ed43c5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:36 +0200 Subject: [PATCH 112/396] drm/vc4: perfmon: Add missing mutex_destroy vc4_perfmon_open_file() will instantiate a mutex for that file instance, but we never call mutex_destroy () in vc4_perfmon_close_file(). Let's add that missing call. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-67-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_perfmon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vc4/vc4_perfmon.c b/drivers/gpu/drm/vc4/vc4_perfmon.c index 79a74184d732..c4ac2c946238 100644 --- a/drivers/gpu/drm/vc4/vc4_perfmon.c +++ b/drivers/gpu/drm/vc4/vc4_perfmon.c @@ -133,6 +133,7 @@ void vc4_perfmon_close_file(struct vc4_file *vc4file) idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, NULL); idr_destroy(&vc4file->perfmon.idr); mutex_unlock(&vc4file->perfmon.lock); + mutex_destroy(&vc4file->perfmon.lock); } int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, From 9b6f461582e6b07e2ce93227a3e4661846e594ad Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:37 +0200 Subject: [PATCH 113/396] drm/vc4: v3d: Stop disabling interrupts The vc4_irq_disable(), among other things, will call disable_irq() to complete any in-flight interrupts. This requires its counterpart, vc4_irq_enable(), to call enable_irq() which causes issues addressed in a later patch. However, vc4_irq_disable() is called by two callees: vc4_irq_uninstall() and vc4_v3d_runtime_suspend(). vc4_irq_uninstall() also calls free_irq() which already disables the interrupt line. We thus don't require an explicit disable_irq() for that call site. vc4_v3d_runtime_suspend() doesn't have any other code. However, the rest of vc4_irq_disable() masks the interrupts coming from the v3d, so explictly disabling the interrupt line is also redundant. The only thing we really care about is thus to make sure we don't have any handler in-flight, as suggested by the comment. We can thus replace disable_irq() by synchronize_irq(). Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-68-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_irq.c | 2 +- drivers/gpu/drm/vc4/vc4_v3d.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index 2eacfb6773d2..a9fc63d9a7f0 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -295,7 +295,7 @@ vc4_irq_disable(struct drm_device *dev) V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); /* Finish any interrupt handler still in flight. */ - disable_irq(vc4->irq); + synchronize_irq(vc4->irq); cancel_work_sync(&vc4->overflow_mem_work); } diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index e7990bed0a96..a2da0db73a5c 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -393,8 +393,6 @@ static int vc4_v3d_runtime_resume(struct device *dev) vc4_v3d_init_hw(&vc4->base); - /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */ - enable_irq(vc4->irq); vc4_irq_enable(&vc4->base); return 0; From 266cff37d7fcec0443e720878242cb52d728138b Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:38 +0200 Subject: [PATCH 114/396] drm/vc4: v3d: Rework the runtime_pm setup At bind time, vc4_v3d_bind() will read a register to retrieve the v3d version and make sure it's a version we're compatible with. However, the v3d has an optional clock that is enabled only after the register read-out and a power domain that wasn't enabled at all in the bind implementation. This was working fine at boot because both were enabled, but resulted in the version check failing if we were unbinding and rebinding the driver because the unbinding would have turned them off. The fix isn't as easy as calling pm_runtime_resume_and_get() prior to the register access to power up the power domain though. Indeed, the runtime_resume implementation will enable the clock mentioned above, call vc4_v3d_init_hw() and then vc4_irq_enable(). Prior to the previous patch, vc4_irq_enable() needed to occur after our call to platform_get_irq() and vc4_irq_install(), since vc4_irq_enable() used to call enable_irq() and vc4_irq_install() will call request_irq(). vc4_irq_install() will also do some register access, so needs the power domain to be on. So we ended up in a situation where vc4_v3d_runtime_resume() needed vc4_irq_install() to have been called before, and vc4_irq_install() needed vc4_v3d_runtime_resume(). The previous patch removed the enable_irq() call in vc4_irq_enable() and thus removed the dependency of vc4_v3d_runtime_resume() on vc4_irq_install(). Thus, we can now rework our bind implementation to call pm_runtime_resume_and_get() before our register access to make sure the power domain is on. vc4_v3d_runtime_resume() also takes care of turning the clock on and calling vc4_v3d_init_hw() so we can remove them from bind. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-69-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_v3d.c | 37 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index a2da0db73a5c..d82c86865079 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -463,41 +463,48 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) } } + ret = platform_get_irq(pdev, 0); + if (ret < 0) + return ret; + vc4->irq = ret; + + pm_runtime_enable(dev); + + ret = pm_runtime_resume_and_get(dev); + if (ret) + goto err_disable_runtime_pm; + if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) { DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n", V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0); - return -EINVAL; + ret = -EINVAL; + goto err_put_runtime_pm; } - ret = clk_prepare_enable(v3d->clk); - if (ret != 0) - return ret; - /* Reset the binner overflow address/size at setup, to be sure * we don't reuse an old one. */ V3D_WRITE(V3D_BPOA, 0); V3D_WRITE(V3D_BPOS, 0); - vc4_v3d_init_hw(drm); - - ret = platform_get_irq(pdev, 0); - if (ret < 0) - return ret; - vc4->irq = ret; - ret = vc4_irq_install(drm, vc4->irq); if (ret) { DRM_ERROR("Failed to install IRQ handler\n"); - return ret; + goto err_put_runtime_pm; } - pm_runtime_set_active(dev); pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ - pm_runtime_enable(dev); return 0; + +err_put_runtime_pm: + pm_runtime_put(dev); + +err_disable_runtime_pm: + pm_runtime_disable(dev); + + return ret; } static void vc4_v3d_unbind(struct device *dev, struct device *master, From 887ddf3251928dc39bfc58c5c62083d38a633c14 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 11 Jul 2022 19:39:39 +0200 Subject: [PATCH 115/396] drm/vc4: v3d: Switch to devm_pm_runtime_enable devm_pm_runtime_enable() simplifies the driver a bit since it will call pm_runtime_disable() automatically through a device-managed action. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220711173939.1132294-70-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_v3d.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index d82c86865079..40f04157ea39 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -468,11 +468,13 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) return ret; vc4->irq = ret; - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; ret = pm_runtime_resume_and_get(dev); if (ret) - goto err_disable_runtime_pm; + return ret; if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) { DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n", @@ -501,9 +503,6 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) err_put_runtime_pm: pm_runtime_put(dev); -err_disable_runtime_pm: - pm_runtime_disable(dev); - return ret; } @@ -513,8 +512,6 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master, struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = to_vc4_dev(drm); - pm_runtime_disable(dev); - vc4_irq_uninstall(drm); /* Disable the binner's overflow memory address, so the next From 94dc3471d1b2b58b3728558d0e3f264e9ce6ff59 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas <javierm@redhat.com> Date: Tue, 5 Jul 2022 12:02:13 +0200 Subject: [PATCH 116/396] drm: Use size_t type for len variable in drm_copy_field() The strlen() function returns a size_t which is an unsigned int on 32-bit arches and an unsigned long on 64-bit arches. But in the drm_copy_field() function, the strlen() return value is assigned to an 'int len' variable. Later, the len variable is passed as copy_from_user() third argument that is an unsigned long parameter as well. In theory, this can lead to an integer overflow via type conversion. Since the assignment happens to a signed int lvalue instead of a size_t lvalue. In practice though, that's unlikely since the values copied are set by DRM drivers and not controlled by userspace. But using a size_t for len is the correct thing to do anyways. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Tested-by: Peter Robinson <pbrobinson@gmail.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220705100215.572498-2-javierm@redhat.com --- drivers/gpu/drm/drm_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 8faad23dc1d8..e1b9a03e619c 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -472,7 +472,7 @@ EXPORT_SYMBOL(drm_invalid_op); */ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) { - int len; + size_t len; /* don't overflow userbuf */ len = strlen(value); From f6ee30407e883042482ad4ad30da5eaba47872ee Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas <javierm@redhat.com> Date: Tue, 5 Jul 2022 12:02:14 +0200 Subject: [PATCH 117/396] drm: Prevent drm_copy_field() to attempt copying a NULL pointer There are some struct drm_driver fields that are required by drivers since drm_copy_field() attempts to copy them to user-space via DRM_IOCTL_VERSION. But it can be possible that a driver has a bug and did not set some of the fields, which leads to drm_copy_field() attempting to copy a NULL pointer: [ +10.395966] Unable to handle kernel access to user memory outside uaccess routines at virtual address 0000000000000000 [ +0.010955] Mem abort info: [ +0.002835] ESR = 0x0000000096000004 [ +0.003872] EC = 0x25: DABT (current EL), IL = 32 bits [ +0.005395] SET = 0, FnV = 0 [ +0.003113] EA = 0, S1PTW = 0 [ +0.003182] FSC = 0x04: level 0 translation fault [ +0.004964] Data abort info: [ +0.002919] ISV = 0, ISS = 0x00000004 [ +0.003886] CM = 0, WnR = 0 [ +0.003040] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000115dad000 [ +0.006536] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000 [ +0.006925] Internal error: Oops: 96000004 [#1] SMP ... [ +0.011113] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ +0.007061] pc : __pi_strlen+0x14/0x150 [ +0.003895] lr : drm_copy_field+0x30/0x1a4 [ +0.004156] sp : ffff8000094b3a50 [ +0.003355] x29: ffff8000094b3a50 x28: ffff8000094b3b70 x27: 0000000000000040 [ +0.007242] x26: ffff443743c2ba00 x25: 0000000000000000 x24: 0000000000000040 [ +0.007243] x23: ffff443743c2ba00 x22: ffff8000094b3b70 x21: 0000000000000000 [ +0.007241] x20: 0000000000000000 x19: ffff8000094b3b90 x18: 0000000000000000 [ +0.007241] x17: 0000000000000000 x16: 0000000000000000 x15: 0000aaab14b9af40 [ +0.007241] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 [ +0.007239] x11: 0000000000000000 x10: 0000000000000000 x9 : ffffa524ad67d4d8 [ +0.007242] x8 : 0101010101010101 x7 : 7f7f7f7f7f7f7f7f x6 : 6c6e6263606e7141 [ +0.007239] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 [ +0.007241] x2 : 0000000000000000 x1 : ffff8000094b3b90 x0 : 0000000000000000 [ +0.007240] Call trace: [ +0.002475] __pi_strlen+0x14/0x150 [ +0.003537] drm_version+0x84/0xac [ +0.003448] drm_ioctl_kernel+0xa8/0x16c [ +0.003975] drm_ioctl+0x270/0x580 [ +0.003448] __arm64_sys_ioctl+0xb8/0xfc [ +0.003978] invoke_syscall+0x78/0x100 [ +0.003799] el0_svc_common.constprop.0+0x4c/0xf4 [ +0.004767] do_el0_svc+0x38/0x4c [ +0.003357] el0_svc+0x34/0x100 [ +0.003185] el0t_64_sync_handler+0x11c/0x150 [ +0.004418] el0t_64_sync+0x190/0x194 [ +0.003716] Code: 92402c04 b200c3e8 f13fc09f 5400088c (a9400c02) [ +0.006180] ---[ end trace 0000000000000000 ]--- Reported-by: Peter Robinson <pbrobinson@gmail.com> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220705100215.572498-3-javierm@redhat.com --- drivers/gpu/drm/drm_ioctl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index e1b9a03e619c..ca2a6e6101dc 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -474,6 +474,12 @@ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) { size_t len; + /* don't attempt to copy a NULL pointer */ + if (WARN_ONCE(!value, "BUG: the value to copy was not set!")) { + *buf_len = 0; + return 0; + } + /* don't overflow userbuf */ len = strlen(value); if (len > *buf_len) From 55b3d6a63fb58e154f0a1ab3930cdd003a39ba9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 14 Jul 2022 14:44:17 +0200 Subject: [PATCH 118/396] drm/amdgpu: reapply "fix start calculation in amdgpu_vram_mgr_new"" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This re-applys commit 5e3f1e7729ec7a99e145e9d8ed58963d86cdfb98. The original problem this was reverted for was found and the correct fix will be merged to drm-misc-next-fixes. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220714132315.587217-1-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 49e4092f447f..51d9d3a4456c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -496,17 +496,23 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, list_splice_tail(trim_list, &vres->blocks); } - list_for_each_entry(block, &vres->blocks, link) + vres->base.start = 0; + list_for_each_entry(block, &vres->blocks, link) { + unsigned long start; + + start = amdgpu_vram_mgr_block_start(block) + + amdgpu_vram_mgr_block_size(block); + start >>= PAGE_SHIFT; + + if (start > vres->base.num_pages) + start -= vres->base.num_pages; + else + start = 0; + vres->base.start = max(vres->base.start, start); + vis_usage += amdgpu_vram_mgr_vis_size(adev, block); - - block = amdgpu_vram_mgr_first_block(&vres->blocks); - if (!block) { - r = -EINVAL; - goto error_fini; } - vres->base.start = amdgpu_vram_mgr_block_start(block) >> PAGE_SHIFT; - if (amdgpu_is_vram_mgr_blocks_contiguous(&vres->blocks)) vres->base.placement |= TTM_PL_FLAG_CONTIGUOUS; From 59dad4a0d1862dcd15405f3217a59b1fac01daf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 14 Jul 2022 14:48:20 +0200 Subject: [PATCH 119/396] drm/amdgpu: re-apply "move internal vram_mgr function into the C file"" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This re-applys commit 708d19d9f362766147cab79eccae60912c6d3068. The original problem this was reverted for was found and the correct fix will be merged to drm-misc-next-fixes. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220714132315.587217-2-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 29 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 27 ------------------ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 51d9d3a4456c..7a5e8a7b4a1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -50,6 +50,35 @@ to_amdgpu_device(struct amdgpu_vram_mgr *mgr) return container_of(mgr, struct amdgpu_device, mman.vram_mgr); } +static inline struct drm_buddy_block * +amdgpu_vram_mgr_first_block(struct list_head *list) +{ + return list_first_entry_or_null(list, struct drm_buddy_block, link); +} + +static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head) +{ + struct drm_buddy_block *block; + u64 start, size; + + block = amdgpu_vram_mgr_first_block(head); + if (!block) + return false; + + while (head != block->link.next) { + start = amdgpu_vram_mgr_block_start(block); + size = amdgpu_vram_mgr_block_size(block); + + block = list_entry(block->link.next, struct drm_buddy_block, link); + if (start + size != amdgpu_vram_mgr_block_start(block)) + return false; + } + + return true; +} + + + /** * DOC: mem_info_vram_total * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h index 9a2db87186c7..4b267bf1c5db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h @@ -53,33 +53,6 @@ static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block) return PAGE_SIZE << drm_buddy_block_order(block); } -static inline struct drm_buddy_block * -amdgpu_vram_mgr_first_block(struct list_head *list) -{ - return list_first_entry_or_null(list, struct drm_buddy_block, link); -} - -static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head) -{ - struct drm_buddy_block *block; - u64 start, size; - - block = amdgpu_vram_mgr_first_block(head); - if (!block) - return false; - - while (head != block->link.next) { - start = amdgpu_vram_mgr_block_start(block); - size = amdgpu_vram_mgr_block_size(block); - - block = list_entry(block->link.next, struct drm_buddy_block, link); - if (start + size != amdgpu_vram_mgr_block_start(block)) - return false; - } - - return true; -} - static inline struct amdgpu_vram_mgr_resource * to_amdgpu_vram_mgr_resource(struct ttm_resource *res) { From bd8408e69a47f8e9f5d95c5d919413fafecc1e73 Mon Sep 17 00:00:00 2001 From: Tom Rix <trix@redhat.com> Date: Sat, 2 Jul 2022 11:39:04 -0400 Subject: [PATCH 120/396] drm/nouveau/bios: set info only when the return is not 0 clang static analysis reports drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c:68:17: warning: The right operand of '*' is a garbage value [core.UndefinedBinaryOperatorResult] switch (!!data * *ver) { ^ ~~~~ A switch statement with only a default should be reduced to an if. If nvbios_pmuEp() returns 0, via the data variable, the output info parameter is not used. So set info only when data is not 0. The struct nvbios_pmuE only has the type and data elements. Since both of these are explicitly set, memset is not needed. So remove it. Signed-off-by: Tom Rix <trix@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220702153904.1696595-1-trix@redhat.com --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c index b4a308f3cf7b..49e2664a734c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c @@ -64,12 +64,9 @@ nvbios_pmuEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, struct nvbios_pmuE *info) { u32 data = nvbios_pmuEe(bios, idx, ver, hdr); - memset(info, 0x00, sizeof(*info)); - switch (!!data * *ver) { - default: + if (data) { info->type = nvbios_rd08(bios, data + 0x00); info->data = nvbios_rd32(bios, data + 0x02); - break; } return data; } From e6d9767faf378e543b064ff204d77753451930df Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:50 +0200 Subject: [PATCH 121/396] drm/via: Rename via_drv to via_dri1 The via driver implements the DRI1 interface, and we have a new implementation of the via driver coming that supports atomic modesetting. It is not acceptable just to replace the existing driver so this is first step to make it a single-file implementation allowing it to stay without interfering with the new driver. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-2-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/{via_drv.c => via_dri1.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/gpu/drm/via/{via_drv.c => via_dri1.c} (100%) diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index 84db4eee7828..acfd916541ea 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o +via-y := via_irq.o via_dri1.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_dri1.c similarity index 100% rename from drivers/gpu/drm/via/via_drv.c rename to drivers/gpu/drm/via/via_dri1.c From 9a4537a7824f6011f628bffdfb57ec0bdc83da39 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:51 +0200 Subject: [PATCH 122/396] drm/via: Embed via_dma in via_dri1 Moved the copyright notices so all copyrights are kept. A few variables was made static as there are no more users outside this file. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-3-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/via_dma.c | 744 --------------------------------- drivers/gpu/drm/via/via_dri1.c | 703 ++++++++++++++++++++++++++++++- drivers/gpu/drm/via/via_drv.h | 3 - 4 files changed, 703 insertions(+), 749 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_dma.c diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index acfd916541ea..824198c0c2ea 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_irq.o via_dri1.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o +via-y := via_irq.o via_dri1.o via_map.o via_mm.o via_verifier.o via_video.o via_dmablit.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c deleted file mode 100644 index 177b0499abf1..000000000000 --- a/drivers/gpu/drm/via/via_dma.c +++ /dev/null @@ -1,744 +0,0 @@ -/* via_dma.c -- DMA support for the VIA Unichrome/Pro - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. - * All Rights Reserved. - * - * Copyright 2004 The Unichrome project. - * All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. - * - * Authors: - * Tungsten Graphics, - * Erdi Chen, - * Thomas Hellstrom. - */ - -#include <linux/delay.h> -#include <linux/uaccess.h> - -#include <drm/drm.h> -#include <drm/drm_device.h> -#include <drm/drm_file.h> -#include <drm/via_drm.h> - -#include "via_drv.h" -#include "via_3d_reg.h" - -#define CMDBUF_ALIGNMENT_SIZE (0x100) -#define CMDBUF_ALIGNMENT_MASK (0x0ff) - -/* defines for VIA 3D registers */ -#define VIA_REG_STATUS 0x400 -#define VIA_REG_TRANSET 0x43C -#define VIA_REG_TRANSPACE 0x440 - -/* VIA_REG_STATUS(0x400): Engine Status */ -#define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */ -#define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */ -#define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */ -#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */ - -#define SetReg2DAGP(nReg, nData) { \ - *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \ - *((uint32_t *)(vb) + 1) = (nData); \ - vb = ((uint32_t *)vb) + 2; \ - dev_priv->dma_low += 8; \ -} - -#define via_flush_write_combine() mb() - -#define VIA_OUT_RING_QW(w1, w2) do { \ - *vb++ = (w1); \ - *vb++ = (w2); \ - dev_priv->dma_low += 8; \ -} while (0) - -static void via_cmdbuf_start(drm_via_private_t *dev_priv); -static void via_cmdbuf_pause(drm_via_private_t *dev_priv); -static void via_cmdbuf_reset(drm_via_private_t *dev_priv); -static void via_cmdbuf_rewind(drm_via_private_t *dev_priv); -static int via_wait_idle(drm_via_private_t *dev_priv); -static void via_pad_cache(drm_via_private_t *dev_priv, int qwords); - -/* - * Free space in command buffer. - */ - -static uint32_t via_cmdbuf_space(drm_via_private_t *dev_priv) -{ - uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; - uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; - - return ((hw_addr <= dev_priv->dma_low) ? - (dev_priv->dma_high + hw_addr - dev_priv->dma_low) : - (hw_addr - dev_priv->dma_low)); -} - -/* - * How much does the command regulator lag behind? - */ - -static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv) -{ - uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; - uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; - - return ((hw_addr <= dev_priv->dma_low) ? - (dev_priv->dma_low - hw_addr) : - (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr)); -} - -/* - * Check that the given size fits in the buffer, otherwise wait. - */ - -static inline int -via_cmdbuf_wait(drm_via_private_t *dev_priv, unsigned int size) -{ - uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; - uint32_t cur_addr, hw_addr, next_addr; - volatile uint32_t *hw_addr_ptr; - uint32_t count; - hw_addr_ptr = dev_priv->hw_addr_ptr; - cur_addr = dev_priv->dma_low; - next_addr = cur_addr + size + 512 * 1024; - count = 1000000; - do { - hw_addr = *hw_addr_ptr - agp_base; - if (count-- == 0) { - DRM_ERROR - ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n", - hw_addr, cur_addr, next_addr); - return -1; - } - if ((cur_addr < hw_addr) && (next_addr >= hw_addr)) - msleep(1); - } while ((cur_addr < hw_addr) && (next_addr >= hw_addr)); - return 0; -} - -/* - * Checks whether buffer head has reach the end. Rewind the ring buffer - * when necessary. - * - * Returns virtual pointer to ring buffer. - */ - -static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv, - unsigned int size) -{ - if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) > - dev_priv->dma_high) { - via_cmdbuf_rewind(dev_priv); - } - if (via_cmdbuf_wait(dev_priv, size) != 0) - return NULL; - - return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); -} - -int via_dma_cleanup(struct drm_device *dev) -{ - if (dev->dev_private) { - drm_via_private_t *dev_priv = - (drm_via_private_t *) dev->dev_private; - - if (dev_priv->ring.virtual_start) { - via_cmdbuf_reset(dev_priv); - - drm_legacy_ioremapfree(&dev_priv->ring.map, dev); - dev_priv->ring.virtual_start = NULL; - } - - } - - return 0; -} - -static int via_initialize(struct drm_device *dev, - drm_via_private_t *dev_priv, - drm_via_dma_init_t *init) -{ - if (!dev_priv || !dev_priv->mmio) { - DRM_ERROR("via_dma_init called before via_map_init\n"); - return -EFAULT; - } - - if (dev_priv->ring.virtual_start != NULL) { - DRM_ERROR("called again without calling cleanup\n"); - return -EFAULT; - } - - if (!dev->agp || !dev->agp->base) { - DRM_ERROR("called with no agp memory available\n"); - return -EFAULT; - } - - if (dev_priv->chipset == VIA_DX9_0) { - DRM_ERROR("AGP DMA is not supported on this chip\n"); - return -EINVAL; - } - - dev_priv->ring.map.offset = dev->agp->base + init->offset; - dev_priv->ring.map.size = init->size; - dev_priv->ring.map.type = 0; - dev_priv->ring.map.flags = 0; - dev_priv->ring.map.mtrr = 0; - - drm_legacy_ioremap(&dev_priv->ring.map, dev); - - if (dev_priv->ring.map.handle == NULL) { - via_dma_cleanup(dev); - DRM_ERROR("can not ioremap virtual address for" - " ring buffer\n"); - return -ENOMEM; - } - - dev_priv->ring.virtual_start = dev_priv->ring.map.handle; - - dev_priv->dma_ptr = dev_priv->ring.virtual_start; - dev_priv->dma_low = 0; - dev_priv->dma_high = init->size; - dev_priv->dma_wrap = init->size; - dev_priv->dma_offset = init->offset; - dev_priv->last_pause_ptr = NULL; - dev_priv->hw_addr_ptr = - (volatile uint32_t *)((char *)dev_priv->mmio->handle + - init->reg_pause_addr); - - via_cmdbuf_start(dev_priv); - - return 0; -} - -static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - drm_via_dma_init_t *init = data; - int retcode = 0; - - switch (init->func) { - case VIA_INIT_DMA: - if (!capable(CAP_SYS_ADMIN)) - retcode = -EPERM; - else - retcode = via_initialize(dev, dev_priv, init); - break; - case VIA_CLEANUP_DMA: - if (!capable(CAP_SYS_ADMIN)) - retcode = -EPERM; - else - retcode = via_dma_cleanup(dev); - break; - case VIA_DMA_INITIALIZED: - retcode = (dev_priv->ring.virtual_start != NULL) ? - 0 : -EFAULT; - break; - default: - retcode = -EINVAL; - break; - } - - return retcode; -} - -static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *cmd) -{ - drm_via_private_t *dev_priv; - uint32_t *vb; - int ret; - - dev_priv = (drm_via_private_t *) dev->dev_private; - - if (dev_priv->ring.virtual_start == NULL) { - DRM_ERROR("called without initializing AGP ring buffer.\n"); - return -EFAULT; - } - - if (cmd->size > VIA_PCI_BUF_SIZE) - return -ENOMEM; - - if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) - return -EFAULT; - - /* - * Running this function on AGP memory is dead slow. Therefore - * we run it on a temporary cacheable system memory buffer and - * copy it to AGP memory when ready. - */ - - if ((ret = - via_verify_command_stream((uint32_t *) dev_priv->pci_buf, - cmd->size, dev, 1))) { - return ret; - } - - vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size); - if (vb == NULL) - return -EAGAIN; - - memcpy(vb, dev_priv->pci_buf, cmd->size); - - dev_priv->dma_low += cmd->size; - - /* - * Small submissions somehow stalls the CPU. (AGP cache effects?) - * pad to greater size. - */ - - if (cmd->size < 0x100) - via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3); - via_cmdbuf_pause(dev_priv); - - return 0; -} - -int via_driver_dma_quiescent(struct drm_device *dev) -{ - drm_via_private_t *dev_priv = dev->dev_private; - - if (!via_wait_idle(dev_priv)) - return -EBUSY; - return 0; -} - -static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - return via_driver_dma_quiescent(dev); -} - -static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_cmdbuffer_t *cmdbuf = data; - int ret; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); - - ret = via_dispatch_cmdbuffer(dev, cmdbuf); - return ret; -} - -static int via_dispatch_pci_cmdbuffer(struct drm_device *dev, - drm_via_cmdbuffer_t *cmd) -{ - drm_via_private_t *dev_priv = dev->dev_private; - int ret; - - if (cmd->size > VIA_PCI_BUF_SIZE) - return -ENOMEM; - if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) - return -EFAULT; - - if ((ret = - via_verify_command_stream((uint32_t *) dev_priv->pci_buf, - cmd->size, dev, 0))) { - return ret; - } - - ret = - via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, - cmd->size); - return ret; -} - -static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_cmdbuffer_t *cmdbuf = data; - int ret; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); - - ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); - return ret; -} - -static inline uint32_t *via_align_buffer(drm_via_private_t *dev_priv, - uint32_t * vb, int qw_count) -{ - for (; qw_count > 0; --qw_count) - VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY); - return vb; -} - -/* - * This function is used internally by ring buffer management code. - * - * Returns virtual pointer to ring buffer. - */ -static inline uint32_t *via_get_dma(drm_via_private_t *dev_priv) -{ - return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); -} - -/* - * Hooks a segment of data into the tail of the ring-buffer by - * modifying the pause address stored in the buffer itself. If - * the regulator has already paused, restart it. - */ -static int via_hook_segment(drm_via_private_t *dev_priv, - uint32_t pause_addr_hi, uint32_t pause_addr_lo, - int no_pci_fire) -{ - int paused, count; - volatile uint32_t *paused_at = dev_priv->last_pause_ptr; - uint32_t reader, ptr; - uint32_t diff; - - paused = 0; - via_flush_write_combine(); - (void) *(volatile uint32_t *)(via_get_dma(dev_priv) - 1); - - *paused_at = pause_addr_lo; - via_flush_write_combine(); - (void) *paused_at; - - reader = *(dev_priv->hw_addr_ptr); - ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + - dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; - - dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; - - /* - * If there is a possibility that the command reader will - * miss the new pause address and pause on the old one, - * In that case we need to program the new start address - * using PCI. - */ - - diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; - count = 10000000; - while (diff == 0 && count--) { - paused = (via_read(dev_priv, 0x41c) & 0x80000000); - if (paused) - break; - reader = *(dev_priv->hw_addr_ptr); - diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; - } - - paused = via_read(dev_priv, 0x41c) & 0x80000000; - - if (paused && !no_pci_fire) { - reader = *(dev_priv->hw_addr_ptr); - diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; - diff &= (dev_priv->dma_high - 1); - if (diff != 0 && diff < (dev_priv->dma_high >> 1)) { - DRM_ERROR("Paused at incorrect address. " - "0x%08x, 0x%08x 0x%08x\n", - ptr, reader, dev_priv->dma_diff); - } else if (diff == 0) { - /* - * There is a concern that these writes may stall the PCI bus - * if the GPU is not idle. However, idling the GPU first - * doesn't make a difference. - */ - - via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); - via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); - via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); - via_read(dev_priv, VIA_REG_TRANSPACE); - } - } - return paused; -} - -static int via_wait_idle(drm_via_private_t *dev_priv) -{ - int count = 10000000; - - while (!(via_read(dev_priv, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) - ; - - while (count && (via_read(dev_priv, VIA_REG_STATUS) & - (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | - VIA_3D_ENG_BUSY))) - --count; - return count; -} - -static uint32_t *via_align_cmd(drm_via_private_t *dev_priv, uint32_t cmd_type, - uint32_t addr, uint32_t *cmd_addr_hi, - uint32_t *cmd_addr_lo, int skip_wait) -{ - uint32_t agp_base; - uint32_t cmd_addr, addr_lo, addr_hi; - uint32_t *vb; - uint32_t qw_pad_count; - - if (!skip_wait) - via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE); - - vb = via_get_dma(dev_priv); - VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) | - (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16); - agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; - qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) - - ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3); - - cmd_addr = (addr) ? addr : - agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3); - addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) | - (cmd_addr & HC_HAGPBpL_MASK)); - addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24)); - - vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1); - VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo); - return vb; -} - -static void via_cmdbuf_start(drm_via_private_t *dev_priv) -{ - uint32_t pause_addr_lo, pause_addr_hi; - uint32_t start_addr, start_addr_lo; - uint32_t end_addr, end_addr_lo; - uint32_t command; - uint32_t agp_base; - uint32_t ptr; - uint32_t reader; - int count; - - dev_priv->dma_low = 0; - - agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; - start_addr = agp_base; - end_addr = agp_base + dev_priv->dma_high; - - start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF)); - end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF)); - command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) | - ((end_addr & 0xff000000) >> 16)); - - dev_priv->last_pause_ptr = - via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, - &pause_addr_hi, &pause_addr_lo, 1) - 1; - - via_flush_write_combine(); - (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; - - via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); - via_write(dev_priv, VIA_REG_TRANSPACE, command); - via_write(dev_priv, VIA_REG_TRANSPACE, start_addr_lo); - via_write(dev_priv, VIA_REG_TRANSPACE, end_addr_lo); - - via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); - via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); - wmb(); - via_write(dev_priv, VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); - via_read(dev_priv, VIA_REG_TRANSPACE); - - dev_priv->dma_diff = 0; - - count = 10000000; - while (!(via_read(dev_priv, 0x41c) & 0x80000000) && count--); - - reader = *(dev_priv->hw_addr_ptr); - ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + - dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; - - /* - * This is the difference between where we tell the - * command reader to pause and where it actually pauses. - * This differs between hw implementation so we need to - * detect it. - */ - - dev_priv->dma_diff = ptr - reader; -} - -static void via_pad_cache(drm_via_private_t *dev_priv, int qwords) -{ - uint32_t *vb; - - via_cmdbuf_wait(dev_priv, qwords + 2); - vb = via_get_dma(dev_priv); - VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16); - via_align_buffer(dev_priv, vb, qwords); -} - -static inline void via_dummy_bitblt(drm_via_private_t *dev_priv) -{ - uint32_t *vb = via_get_dma(dev_priv); - SetReg2DAGP(0x0C, (0 | (0 << 16))); - SetReg2DAGP(0x10, 0 | (0 << 16)); - SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000); -} - -static void via_cmdbuf_jump(drm_via_private_t *dev_priv) -{ - uint32_t pause_addr_lo, pause_addr_hi; - uint32_t jump_addr_lo, jump_addr_hi; - volatile uint32_t *last_pause_ptr; - uint32_t dma_low_save1, dma_low_save2; - - via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, - &jump_addr_lo, 0); - - dev_priv->dma_wrap = dev_priv->dma_low; - - /* - * Wrap command buffer to the beginning. - */ - - dev_priv->dma_low = 0; - if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) - DRM_ERROR("via_cmdbuf_jump failed\n"); - - via_dummy_bitblt(dev_priv); - via_dummy_bitblt(dev_priv); - - last_pause_ptr = - via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, - &pause_addr_lo, 0) - 1; - via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, - &pause_addr_lo, 0); - - *last_pause_ptr = pause_addr_lo; - dma_low_save1 = dev_priv->dma_low; - - /* - * Now, set a trap that will pause the regulator if it tries to rerun the old - * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause - * and reissues the jump command over PCI, while the regulator has already taken the jump - * and actually paused at the current buffer end). - * There appears to be no other way to detect this condition, since the hw_addr_pointer - * does not seem to get updated immediately when a jump occurs. - */ - - last_pause_ptr = - via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, - &pause_addr_lo, 0) - 1; - via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, - &pause_addr_lo, 0); - *last_pause_ptr = pause_addr_lo; - - dma_low_save2 = dev_priv->dma_low; - dev_priv->dma_low = dma_low_save1; - via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); - dev_priv->dma_low = dma_low_save2; - via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); -} - - -static void via_cmdbuf_rewind(drm_via_private_t *dev_priv) -{ - via_cmdbuf_jump(dev_priv); -} - -static void via_cmdbuf_flush(drm_via_private_t *dev_priv, uint32_t cmd_type) -{ - uint32_t pause_addr_lo, pause_addr_hi; - - via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0); - via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); -} - -static void via_cmdbuf_pause(drm_via_private_t *dev_priv) -{ - via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE); -} - -static void via_cmdbuf_reset(drm_via_private_t *dev_priv) -{ - via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP); - via_wait_idle(dev_priv); -} - -/* - * User interface to the space and lag functions. - */ - -static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_cmdbuf_size_t *d_siz = data; - int ret = 0; - uint32_t tmp_size, count; - drm_via_private_t *dev_priv; - - DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); - - dev_priv = (drm_via_private_t *) dev->dev_private; - - if (dev_priv->ring.virtual_start == NULL) { - DRM_ERROR("called without initializing AGP ring buffer.\n"); - return -EFAULT; - } - - count = 1000000; - tmp_size = d_siz->size; - switch (d_siz->func) { - case VIA_CMDBUF_SPACE: - while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size) - && --count) { - if (!d_siz->wait) - break; - } - if (!count) { - DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n"); - ret = -EAGAIN; - } - break; - case VIA_CMDBUF_LAG: - while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size) - && --count) { - if (!d_siz->wait) - break; - } - if (!count) { - DRM_ERROR("VIA_CMDBUF_LAG timed out.\n"); - ret = -EAGAIN; - } - break; - default: - ret = -EFAULT; - } - d_siz->size = tmp_size; - - return ret; -} - -const struct drm_ioctl_desc via_ioctls[] = { - DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), - DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), - DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), - DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), - DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) -}; - -int via_max_ioctl = ARRAY_SIZE(via_ioctls); diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index 5da38082821f..d5d4a64437da 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -1,7 +1,10 @@ /* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. - * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. All Rights Reserved. + * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. All Rights Reserved. + * Copyright 2004 The Unichrome project. All Rights Reserved. + * * 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 @@ -22,6 +25,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include <linux/delay.h> #include <linux/module.h> #include <linux/pci.h> @@ -31,8 +35,705 @@ #include <drm/via_drm.h> #include "via_drv.h" +#include "via_3d_reg.h" + +#define CMDBUF_ALIGNMENT_SIZE (0x100) +#define CMDBUF_ALIGNMENT_MASK (0x0ff) + +/* defines for VIA 3D registers */ +#define VIA_REG_STATUS 0x400 +#define VIA_REG_TRANSET 0x43C +#define VIA_REG_TRANSPACE 0x440 + +/* VIA_REG_STATUS(0x400): Engine Status */ +#define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */ +#define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */ +#define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */ +#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */ + +#define SetReg2DAGP(nReg, nData) { \ + *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \ + *((uint32_t *)(vb) + 1) = (nData); \ + vb = ((uint32_t *)vb) + 2; \ + dev_priv->dma_low += 8; \ +} + +#define via_flush_write_combine() mb() + +#define VIA_OUT_RING_QW(w1, w2) do { \ + *vb++ = (w1); \ + *vb++ = (w2); \ + dev_priv->dma_low += 8; \ +} while (0) + +static void via_cmdbuf_start(drm_via_private_t *dev_priv); +static void via_cmdbuf_pause(drm_via_private_t *dev_priv); +static void via_cmdbuf_reset(drm_via_private_t *dev_priv); +static void via_cmdbuf_rewind(drm_via_private_t *dev_priv); +static int via_wait_idle(drm_via_private_t *dev_priv); +static void via_pad_cache(drm_via_private_t *dev_priv, int qwords); + +/* + * Free space in command buffer. + */ + +static uint32_t via_cmdbuf_space(drm_via_private_t *dev_priv) +{ + uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; + uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; + + return ((hw_addr <= dev_priv->dma_low) ? + (dev_priv->dma_high + hw_addr - dev_priv->dma_low) : + (hw_addr - dev_priv->dma_low)); +} + +/* + * How much does the command regulator lag behind? + */ + +static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv) +{ + uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; + uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; + + return ((hw_addr <= dev_priv->dma_low) ? + (dev_priv->dma_low - hw_addr) : + (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr)); +} + +/* + * Check that the given size fits in the buffer, otherwise wait. + */ + +static inline int +via_cmdbuf_wait(drm_via_private_t *dev_priv, unsigned int size) +{ + uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; + uint32_t cur_addr, hw_addr, next_addr; + volatile uint32_t *hw_addr_ptr; + uint32_t count; + hw_addr_ptr = dev_priv->hw_addr_ptr; + cur_addr = dev_priv->dma_low; + next_addr = cur_addr + size + 512 * 1024; + count = 1000000; + do { + hw_addr = *hw_addr_ptr - agp_base; + if (count-- == 0) { + DRM_ERROR + ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n", + hw_addr, cur_addr, next_addr); + return -1; + } + if ((cur_addr < hw_addr) && (next_addr >= hw_addr)) + msleep(1); + } while ((cur_addr < hw_addr) && (next_addr >= hw_addr)); + return 0; +} + +/* + * Checks whether buffer head has reach the end. Rewind the ring buffer + * when necessary. + * + * Returns virtual pointer to ring buffer. + */ + +static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv, + unsigned int size) +{ + if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) > + dev_priv->dma_high) { + via_cmdbuf_rewind(dev_priv); + } + if (via_cmdbuf_wait(dev_priv, size) != 0) + return NULL; + + return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); +} + +int via_dma_cleanup(struct drm_device *dev) +{ + if (dev->dev_private) { + drm_via_private_t *dev_priv = + (drm_via_private_t *) dev->dev_private; + + if (dev_priv->ring.virtual_start) { + via_cmdbuf_reset(dev_priv); + + drm_legacy_ioremapfree(&dev_priv->ring.map, dev); + dev_priv->ring.virtual_start = NULL; + } + + } + + return 0; +} + +static int via_initialize(struct drm_device *dev, + drm_via_private_t *dev_priv, + drm_via_dma_init_t *init) +{ + if (!dev_priv || !dev_priv->mmio) { + DRM_ERROR("via_dma_init called before via_map_init\n"); + return -EFAULT; + } + + if (dev_priv->ring.virtual_start != NULL) { + DRM_ERROR("called again without calling cleanup\n"); + return -EFAULT; + } + + if (!dev->agp || !dev->agp->base) { + DRM_ERROR("called with no agp memory available\n"); + return -EFAULT; + } + + if (dev_priv->chipset == VIA_DX9_0) { + DRM_ERROR("AGP DMA is not supported on this chip\n"); + return -EINVAL; + } + + dev_priv->ring.map.offset = dev->agp->base + init->offset; + dev_priv->ring.map.size = init->size; + dev_priv->ring.map.type = 0; + dev_priv->ring.map.flags = 0; + dev_priv->ring.map.mtrr = 0; + + drm_legacy_ioremap(&dev_priv->ring.map, dev); + + if (dev_priv->ring.map.handle == NULL) { + via_dma_cleanup(dev); + DRM_ERROR("can not ioremap virtual address for" + " ring buffer\n"); + return -ENOMEM; + } + + dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + + dev_priv->dma_ptr = dev_priv->ring.virtual_start; + dev_priv->dma_low = 0; + dev_priv->dma_high = init->size; + dev_priv->dma_wrap = init->size; + dev_priv->dma_offset = init->offset; + dev_priv->last_pause_ptr = NULL; + dev_priv->hw_addr_ptr = + (volatile uint32_t *)((char *)dev_priv->mmio->handle + + init->reg_pause_addr); + + via_cmdbuf_start(dev_priv); + + return 0; +} + +static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + drm_via_dma_init_t *init = data; + int retcode = 0; + + switch (init->func) { + case VIA_INIT_DMA: + if (!capable(CAP_SYS_ADMIN)) + retcode = -EPERM; + else + retcode = via_initialize(dev, dev_priv, init); + break; + case VIA_CLEANUP_DMA: + if (!capable(CAP_SYS_ADMIN)) + retcode = -EPERM; + else + retcode = via_dma_cleanup(dev); + break; + case VIA_DMA_INITIALIZED: + retcode = (dev_priv->ring.virtual_start != NULL) ? + 0 : -EFAULT; + break; + default: + retcode = -EINVAL; + break; + } + + return retcode; +} + +static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *cmd) +{ + drm_via_private_t *dev_priv; + uint32_t *vb; + int ret; + + dev_priv = (drm_via_private_t *) dev->dev_private; + + if (dev_priv->ring.virtual_start == NULL) { + DRM_ERROR("called without initializing AGP ring buffer.\n"); + return -EFAULT; + } + + if (cmd->size > VIA_PCI_BUF_SIZE) + return -ENOMEM; + + if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) + return -EFAULT; + + /* + * Running this function on AGP memory is dead slow. Therefore + * we run it on a temporary cacheable system memory buffer and + * copy it to AGP memory when ready. + */ + + if ((ret = + via_verify_command_stream((uint32_t *) dev_priv->pci_buf, + cmd->size, dev, 1))) { + return ret; + } + + vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size); + if (vb == NULL) + return -EAGAIN; + + memcpy(vb, dev_priv->pci_buf, cmd->size); + + dev_priv->dma_low += cmd->size; + + /* + * Small submissions somehow stalls the CPU. (AGP cache effects?) + * pad to greater size. + */ + + if (cmd->size < 0x100) + via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3); + via_cmdbuf_pause(dev_priv); + + return 0; +} + +int via_driver_dma_quiescent(struct drm_device *dev) +{ + drm_via_private_t *dev_priv = dev->dev_private; + + if (!via_wait_idle(dev_priv)) + return -EBUSY; + return 0; +} + +static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + return via_driver_dma_quiescent(dev); +} + +static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_cmdbuffer_t *cmdbuf = data; + int ret; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); + + ret = via_dispatch_cmdbuffer(dev, cmdbuf); + return ret; +} + +static int via_dispatch_pci_cmdbuffer(struct drm_device *dev, + drm_via_cmdbuffer_t *cmd) +{ + drm_via_private_t *dev_priv = dev->dev_private; + int ret; + + if (cmd->size > VIA_PCI_BUF_SIZE) + return -ENOMEM; + if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) + return -EFAULT; + + if ((ret = + via_verify_command_stream((uint32_t *) dev_priv->pci_buf, + cmd->size, dev, 0))) { + return ret; + } + + ret = + via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, + cmd->size); + return ret; +} + +static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_cmdbuffer_t *cmdbuf = data; + int ret; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); + + ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); + return ret; +} + +static inline uint32_t *via_align_buffer(drm_via_private_t *dev_priv, + uint32_t * vb, int qw_count) +{ + for (; qw_count > 0; --qw_count) + VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY); + return vb; +} + +/* + * This function is used internally by ring buffer management code. + * + * Returns virtual pointer to ring buffer. + */ +static inline uint32_t *via_get_dma(drm_via_private_t *dev_priv) +{ + return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); +} + +/* + * Hooks a segment of data into the tail of the ring-buffer by + * modifying the pause address stored in the buffer itself. If + * the regulator has already paused, restart it. + */ +static int via_hook_segment(drm_via_private_t *dev_priv, + uint32_t pause_addr_hi, uint32_t pause_addr_lo, + int no_pci_fire) +{ + int paused, count; + volatile uint32_t *paused_at = dev_priv->last_pause_ptr; + uint32_t reader, ptr; + uint32_t diff; + + paused = 0; + via_flush_write_combine(); + (void) *(volatile uint32_t *)(via_get_dma(dev_priv) - 1); + + *paused_at = pause_addr_lo; + via_flush_write_combine(); + (void) *paused_at; + + reader = *(dev_priv->hw_addr_ptr); + ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + + dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; + + dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; + + /* + * If there is a possibility that the command reader will + * miss the new pause address and pause on the old one, + * In that case we need to program the new start address + * using PCI. + */ + + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; + count = 10000000; + while (diff == 0 && count--) { + paused = (via_read(dev_priv, 0x41c) & 0x80000000); + if (paused) + break; + reader = *(dev_priv->hw_addr_ptr); + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; + } + + paused = via_read(dev_priv, 0x41c) & 0x80000000; + + if (paused && !no_pci_fire) { + reader = *(dev_priv->hw_addr_ptr); + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; + diff &= (dev_priv->dma_high - 1); + if (diff != 0 && diff < (dev_priv->dma_high >> 1)) { + DRM_ERROR("Paused at incorrect address. " + "0x%08x, 0x%08x 0x%08x\n", + ptr, reader, dev_priv->dma_diff); + } else if (diff == 0) { + /* + * There is a concern that these writes may stall the PCI bus + * if the GPU is not idle. However, idling the GPU first + * doesn't make a difference. + */ + + via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); + via_read(dev_priv, VIA_REG_TRANSPACE); + } + } + return paused; +} + +static int via_wait_idle(drm_via_private_t *dev_priv) +{ + int count = 10000000; + + while (!(via_read(dev_priv, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) + ; + + while (count && (via_read(dev_priv, VIA_REG_STATUS) & + (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | + VIA_3D_ENG_BUSY))) + --count; + return count; +} + +static uint32_t *via_align_cmd(drm_via_private_t *dev_priv, uint32_t cmd_type, + uint32_t addr, uint32_t *cmd_addr_hi, + uint32_t *cmd_addr_lo, int skip_wait) +{ + uint32_t agp_base; + uint32_t cmd_addr, addr_lo, addr_hi; + uint32_t *vb; + uint32_t qw_pad_count; + + if (!skip_wait) + via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE); + + vb = via_get_dma(dev_priv); + VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) | + (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16); + agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; + qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) - + ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3); + + cmd_addr = (addr) ? addr : + agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3); + addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) | + (cmd_addr & HC_HAGPBpL_MASK)); + addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24)); + + vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1); + VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo); + return vb; +} + +static void via_cmdbuf_start(drm_via_private_t *dev_priv) +{ + uint32_t pause_addr_lo, pause_addr_hi; + uint32_t start_addr, start_addr_lo; + uint32_t end_addr, end_addr_lo; + uint32_t command; + uint32_t agp_base; + uint32_t ptr; + uint32_t reader; + int count; + + dev_priv->dma_low = 0; + + agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; + start_addr = agp_base; + end_addr = agp_base + dev_priv->dma_high; + + start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF)); + end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF)); + command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) | + ((end_addr & 0xff000000) >> 16)); + + dev_priv->last_pause_ptr = + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, + &pause_addr_hi, &pause_addr_lo, 1) - 1; + + via_flush_write_combine(); + (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; + + via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); + via_write(dev_priv, VIA_REG_TRANSPACE, command); + via_write(dev_priv, VIA_REG_TRANSPACE, start_addr_lo); + via_write(dev_priv, VIA_REG_TRANSPACE, end_addr_lo); + + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); + wmb(); + via_write(dev_priv, VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); + via_read(dev_priv, VIA_REG_TRANSPACE); + + dev_priv->dma_diff = 0; + + count = 10000000; + while (!(via_read(dev_priv, 0x41c) & 0x80000000) && count--); + + reader = *(dev_priv->hw_addr_ptr); + ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + + dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; + + /* + * This is the difference between where we tell the + * command reader to pause and where it actually pauses. + * This differs between hw implementation so we need to + * detect it. + */ + + dev_priv->dma_diff = ptr - reader; +} + +static void via_pad_cache(drm_via_private_t *dev_priv, int qwords) +{ + uint32_t *vb; + + via_cmdbuf_wait(dev_priv, qwords + 2); + vb = via_get_dma(dev_priv); + VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16); + via_align_buffer(dev_priv, vb, qwords); +} + +static inline void via_dummy_bitblt(drm_via_private_t *dev_priv) +{ + uint32_t *vb = via_get_dma(dev_priv); + SetReg2DAGP(0x0C, (0 | (0 << 16))); + SetReg2DAGP(0x10, 0 | (0 << 16)); + SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000); +} + +static void via_cmdbuf_jump(drm_via_private_t *dev_priv) +{ + uint32_t pause_addr_lo, pause_addr_hi; + uint32_t jump_addr_lo, jump_addr_hi; + volatile uint32_t *last_pause_ptr; + uint32_t dma_low_save1, dma_low_save2; + + via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, + &jump_addr_lo, 0); + + dev_priv->dma_wrap = dev_priv->dma_low; + + /* + * Wrap command buffer to the beginning. + */ + + dev_priv->dma_low = 0; + if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) + DRM_ERROR("via_cmdbuf_jump failed\n"); + + via_dummy_bitblt(dev_priv); + via_dummy_bitblt(dev_priv); + + last_pause_ptr = + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0) - 1; + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0); + + *last_pause_ptr = pause_addr_lo; + dma_low_save1 = dev_priv->dma_low; + + /* + * Now, set a trap that will pause the regulator if it tries to rerun the old + * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause + * and reissues the jump command over PCI, while the regulator has already taken the jump + * and actually paused at the current buffer end). + * There appears to be no other way to detect this condition, since the hw_addr_pointer + * does not seem to get updated immediately when a jump occurs. + */ + + last_pause_ptr = + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0) - 1; + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0); + *last_pause_ptr = pause_addr_lo; + + dma_low_save2 = dev_priv->dma_low; + dev_priv->dma_low = dma_low_save1; + via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); + dev_priv->dma_low = dma_low_save2; + via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); +} +static void via_cmdbuf_rewind(drm_via_private_t *dev_priv) +{ + via_cmdbuf_jump(dev_priv); +} + +static void via_cmdbuf_flush(drm_via_private_t *dev_priv, uint32_t cmd_type) +{ + uint32_t pause_addr_lo, pause_addr_hi; + + via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0); + via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); +} + +static void via_cmdbuf_pause(drm_via_private_t *dev_priv) +{ + via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE); +} + +static void via_cmdbuf_reset(drm_via_private_t *dev_priv) +{ + via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP); + via_wait_idle(dev_priv); +} + +/* + * User interface to the space and lag functions. + */ + +static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_cmdbuf_size_t *d_siz = data; + int ret = 0; + uint32_t tmp_size, count; + drm_via_private_t *dev_priv; + + DRM_DEBUG("\n"); + LOCK_TEST_WITH_RETURN(dev, file_priv); + + dev_priv = (drm_via_private_t *) dev->dev_private; + + if (dev_priv->ring.virtual_start == NULL) { + DRM_ERROR("called without initializing AGP ring buffer.\n"); + return -EFAULT; + } + + count = 1000000; + tmp_size = d_siz->size; + switch (d_siz->func) { + case VIA_CMDBUF_SPACE: + while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size) + && --count) { + if (!d_siz->wait) + break; + } + if (!count) { + DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n"); + ret = -EAGAIN; + } + break; + case VIA_CMDBUF_LAG: + while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size) + && --count) { + if (!d_siz->wait) + break; + } + if (!count) { + DRM_ERROR("VIA_CMDBUF_LAG timed out.\n"); + ret = -EAGAIN; + } + break; + default: + ret = -EFAULT; + } + d_siz->size = tmp_size; + + return ret; +} + +static const struct drm_ioctl_desc via_ioctls[] = { + DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) +}; + +static int via_max_ioctl = ARRAY_SIZE(via_ioctls); static int via_driver_open(struct drm_device *dev, struct drm_file *file) { struct via_file_private *file_priv; diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index d5ad1b05bf77..5757422ea634 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -183,9 +183,6 @@ do { \ remove_wait_queue(&(queue), &entry); \ } while (0) -extern const struct drm_ioctl_desc via_ioctls[]; -extern int via_max_ioctl; - extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); From fa0cc3ca1df89e96c20c2aa229363bfc1670068b Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:52 +0200 Subject: [PATCH 123/396] drm/via: Embed via_map in via_dri1 A few functions has no external use and are made static. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-4-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/via_dri1.c | 102 +++++++++++++++++++++++++ drivers/gpu/drm/via/via_drv.h | 4 - drivers/gpu/drm/via/via_map.c | 132 --------------------------------- 4 files changed, 103 insertions(+), 137 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_map.c diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index 824198c0c2ea..be12cbfa4d7f 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_irq.o via_dri1.o via_map.o via_mm.o via_verifier.o via_video.o via_dmablit.o +via-y := via_irq.o via_dri1.o via_mm.o via_verifier.o via_video.o via_dmablit.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index d5d4a64437da..2fa22359b1f6 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -32,6 +32,7 @@ #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_pciids.h> +#include <drm/drm_vblank.h> #include <drm/via_drm.h> #include "via_drv.h" @@ -66,6 +67,107 @@ dev_priv->dma_low += 8; \ } while (0) +static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init) +{ + drm_via_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + dev_priv->sarea = drm_legacy_getsarea(dev); + if (!dev_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + dev_priv->fb = drm_legacy_findmap(dev, init->fb_offset); + if (!dev_priv->fb) { + DRM_ERROR("could not find framebuffer!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset); + if (!dev_priv->mmio) { + DRM_ERROR("could not find mmio region!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + dev_priv->sarea_priv = + (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle + + init->sarea_priv_offset); + + dev_priv->agpAddr = init->agpAddr; + + via_init_futex(dev_priv); + + via_init_dmablit(dev); + + dev->dev_private = (void *)dev_priv; + return 0; +} + +int via_do_cleanup_map(struct drm_device *dev) +{ + via_dma_cleanup(dev); + + return 0; +} + +static int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_init_t *init = data; + + DRM_DEBUG("\n"); + + switch (init->func) { + case VIA_INIT_MAP: + return via_do_init_map(dev, init); + case VIA_CLEANUP_MAP: + return via_do_cleanup_map(dev); + } + + return -EINVAL; +} + +static int via_driver_load(struct drm_device *dev, unsigned long chipset) +{ + struct pci_dev *pdev = to_pci_dev(dev->dev); + drm_via_private_t *dev_priv; + int ret = 0; + + dev_priv = kzalloc(sizeof(drm_via_private_t), GFP_KERNEL); + if (dev_priv == NULL) + return -ENOMEM; + + idr_init(&dev_priv->object_idr); + dev->dev_private = (void *)dev_priv; + + dev_priv->chipset = chipset; + + pci_set_master(pdev); + + ret = drm_vblank_init(dev, 1); + if (ret) { + kfree(dev_priv); + return ret; + } + + return 0; +} + +static void via_driver_unload(struct drm_device *dev) +{ + drm_via_private_t *dev_priv = dev->dev_private; + + idr_destroy(&dev_priv->object_idr); + + kfree(dev_priv); +} + static void via_cmdbuf_start(drm_via_private_t *dev_priv); static void via_cmdbuf_pause(drm_via_private_t *dev_priv); static void via_cmdbuf_reset(drm_via_private_t *dev_priv); diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 5757422ea634..4eaad17c0e02 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -187,15 +187,11 @@ extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int via_driver_load(struct drm_device *dev, unsigned long chipset); -extern void via_driver_unload(struct drm_device *dev); - extern int via_init_context(struct drm_device *dev, int context); extern int via_final_context(struct drm_device *dev, int context); diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c deleted file mode 100644 index a9f6b0c11966..000000000000 --- a/drivers/gpu/drm/via/via_map.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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. - */ - -#include <linux/pci.h> - -#include <drm/drm_device.h> -#include <drm/drm_vblank.h> -#include <drm/via_drm.h> - -#include "via_drv.h" - -static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init) -{ - drm_via_private_t *dev_priv = dev->dev_private; - - DRM_DEBUG("\n"); - - dev_priv->sarea = drm_legacy_getsarea(dev); - if (!dev_priv->sarea) { - DRM_ERROR("could not find sarea!\n"); - dev->dev_private = (void *)dev_priv; - via_do_cleanup_map(dev); - return -EINVAL; - } - - dev_priv->fb = drm_legacy_findmap(dev, init->fb_offset); - if (!dev_priv->fb) { - DRM_ERROR("could not find framebuffer!\n"); - dev->dev_private = (void *)dev_priv; - via_do_cleanup_map(dev); - return -EINVAL; - } - dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio) { - DRM_ERROR("could not find mmio region!\n"); - dev->dev_private = (void *)dev_priv; - via_do_cleanup_map(dev); - return -EINVAL; - } - - dev_priv->sarea_priv = - (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle + - init->sarea_priv_offset); - - dev_priv->agpAddr = init->agpAddr; - - via_init_futex(dev_priv); - - via_init_dmablit(dev); - - dev->dev_private = (void *)dev_priv; - return 0; -} - -int via_do_cleanup_map(struct drm_device *dev) -{ - via_dma_cleanup(dev); - - return 0; -} - -int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_init_t *init = data; - - DRM_DEBUG("\n"); - - switch (init->func) { - case VIA_INIT_MAP: - return via_do_init_map(dev, init); - case VIA_CLEANUP_MAP: - return via_do_cleanup_map(dev); - } - - return -EINVAL; -} - -int via_driver_load(struct drm_device *dev, unsigned long chipset) -{ - struct pci_dev *pdev = to_pci_dev(dev->dev); - drm_via_private_t *dev_priv; - int ret = 0; - - dev_priv = kzalloc(sizeof(drm_via_private_t), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - - idr_init(&dev_priv->object_idr); - dev->dev_private = (void *)dev_priv; - - dev_priv->chipset = chipset; - - pci_set_master(pdev); - - ret = drm_vblank_init(dev, 1); - if (ret) { - kfree(dev_priv); - return ret; - } - - return 0; -} - -void via_driver_unload(struct drm_device *dev) -{ - drm_via_private_t *dev_priv = dev->dev_private; - - idr_destroy(&dev_priv->object_idr); - - kfree(dev_priv); -} From 67034c8e004982764dd5b5df3d57a4179902f60d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:53 +0200 Subject: [PATCH 124/396] drm/via: Embed via_mm in via_dri1 All functions was made static as there are no external users. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-5-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/via_dri1.c | 208 ++++++++++++++++++++++++++++ drivers/gpu/drm/via/via_drv.h | 9 -- drivers/gpu/drm/via/via_mm.c | 241 --------------------------------- 4 files changed, 209 insertions(+), 251 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_mm.c diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index be12cbfa4d7f..daadc0d3233f 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_irq.o via_dri1.o via_mm.o via_verifier.o via_video.o via_dmablit.o +via-y := via_irq.o via_dri1.o via_verifier.o via_video.o via_dmablit.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index 2fa22359b1f6..3ebe17649ec2 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -2,6 +2,7 @@ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. All Rights Reserved. + * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA. * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. All Rights Reserved. * Copyright 2004 The Unichrome project. All Rights Reserved. * @@ -67,6 +68,213 @@ dev_priv->dma_low += 8; \ } while (0) +#define VIA_MM_ALIGN_SHIFT 4 +#define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1) + +struct via_memblock { + struct drm_mm_node mm_node; + struct list_head owner_list; +}; + +static int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_agp_t *agp = data; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + + mutex_lock(&dev->struct_mutex); + drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT); + + dev_priv->agp_initialized = 1; + dev_priv->agp_offset = agp->offset; + mutex_unlock(&dev->struct_mutex); + + DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); + return 0; +} + +static int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_fb_t *fb = data; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + + mutex_lock(&dev->struct_mutex); + drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT); + + dev_priv->vram_initialized = 1; + dev_priv->vram_offset = fb->offset; + + mutex_unlock(&dev->struct_mutex); + DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); + + return 0; + +} + +static int via_final_context(struct drm_device *dev, int context) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + + via_release_futex(dev_priv, context); + + /* Linux specific until context tracking code gets ported to BSD */ + /* Last context, perform cleanup */ + if (list_is_singular(&dev->ctxlist)) { + DRM_DEBUG("Last Context\n"); + drm_legacy_irq_uninstall(dev); + via_cleanup_futex(dev_priv); + via_do_cleanup_map(dev); + } + return 1; +} + +static void via_lastclose(struct drm_device *dev) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + + if (!dev_priv) + return; + + mutex_lock(&dev->struct_mutex); + if (dev_priv->vram_initialized) { + drm_mm_takedown(&dev_priv->vram_mm); + dev_priv->vram_initialized = 0; + } + if (dev_priv->agp_initialized) { + drm_mm_takedown(&dev_priv->agp_mm); + dev_priv->agp_initialized = 0; + } + mutex_unlock(&dev->struct_mutex); +} + +static int via_mem_alloc(struct drm_device *dev, void *data, + struct drm_file *file) +{ + drm_via_mem_t *mem = data; + int retval = 0, user_key; + struct via_memblock *item; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + struct via_file_private *file_priv = file->driver_priv; + unsigned long tmpSize; + + if (mem->type > VIA_MEM_AGP) { + DRM_ERROR("Unknown memory type allocation\n"); + return -EINVAL; + } + mutex_lock(&dev->struct_mutex); + if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : + dev_priv->agp_initialized)) { + mutex_unlock(&dev->struct_mutex); + DRM_ERROR + ("Attempt to allocate from uninitialized memory manager.\n"); + return -EINVAL; + } + + item = kzalloc(sizeof(*item), GFP_KERNEL); + if (!item) { + retval = -ENOMEM; + goto fail_alloc; + } + + tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; + if (mem->type == VIA_MEM_AGP) + retval = drm_mm_insert_node(&dev_priv->agp_mm, + &item->mm_node, + tmpSize); + else + retval = drm_mm_insert_node(&dev_priv->vram_mm, + &item->mm_node, + tmpSize); + if (retval) + goto fail_alloc; + + retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL); + if (retval < 0) + goto fail_idr; + user_key = retval; + + list_add(&item->owner_list, &file_priv->obj_list); + mutex_unlock(&dev->struct_mutex); + + mem->offset = ((mem->type == VIA_MEM_VIDEO) ? + dev_priv->vram_offset : dev_priv->agp_offset) + + ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT); + mem->index = user_key; + + return 0; + +fail_idr: + drm_mm_remove_node(&item->mm_node); +fail_alloc: + kfree(item); + mutex_unlock(&dev->struct_mutex); + + mem->offset = 0; + mem->size = 0; + mem->index = 0; + DRM_DEBUG("Video memory allocation failed\n"); + + return retval; +} + +static int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_private_t *dev_priv = dev->dev_private; + drm_via_mem_t *mem = data; + struct via_memblock *obj; + + mutex_lock(&dev->struct_mutex); + obj = idr_find(&dev_priv->object_idr, mem->index); + if (obj == NULL) { + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + idr_remove(&dev_priv->object_idr, mem->index); + list_del(&obj->owner_list); + drm_mm_remove_node(&obj->mm_node); + kfree(obj); + mutex_unlock(&dev->struct_mutex); + + DRM_DEBUG("free = 0x%lx\n", mem->index); + + return 0; +} + + +static void via_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file) +{ + struct via_file_private *file_priv = file->driver_priv; + struct via_memblock *entry, *next; + + if (!(dev->master && file->master->lock.hw_lock)) + return; + + drm_legacy_idlelock_take(&file->master->lock); + + mutex_lock(&dev->struct_mutex); + if (list_empty(&file_priv->obj_list)) { + mutex_unlock(&dev->struct_mutex); + drm_legacy_idlelock_release(&file->master->lock); + + return; + } + + via_driver_dma_quiescent(dev); + + list_for_each_entry_safe(entry, next, &file_priv->obj_list, + owner_list) { + list_del(&entry->owner_list); + drm_mm_remove_node(&entry->mm_node); + kfree(entry); + } + mutex_unlock(&dev->struct_mutex); + + drm_legacy_idlelock_release(&file->master->lock); + + return; +} + static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init) { drm_via_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 4eaad17c0e02..c1a5fdf0bc4b 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -183,17 +183,12 @@ do { \ remove_wait_queue(&(queue), &entry); \ } while (0) -extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_init_context(struct drm_device *dev, int context); -extern int via_final_context(struct drm_device *dev, int context); extern int via_do_cleanup_map(struct drm_device *dev); extern u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe); @@ -212,10 +207,6 @@ extern void via_init_futex(drm_via_private_t *dev_priv); extern void via_cleanup_futex(drm_via_private_t *dev_priv); extern void via_release_futex(drm_via_private_t *dev_priv, int context); -extern void via_reclaim_buffers_locked(struct drm_device *dev, - struct drm_file *file_priv); -extern void via_lastclose(struct drm_device *dev); - extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq); extern void via_init_dmablit(struct drm_device *dev); diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c deleted file mode 100644 index c9afa1a51f23..000000000000 --- a/drivers/gpu/drm/via/via_mm.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA. - * All rights reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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. - */ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#include <linux/slab.h> - -#include <drm/drm_device.h> -#include <drm/drm_file.h> -#include <drm/via_drm.h> - -#include "via_drv.h" - -#define VIA_MM_ALIGN_SHIFT 4 -#define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1) - -struct via_memblock { - struct drm_mm_node mm_node; - struct list_head owner_list; -}; - -int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_agp_t *agp = data; - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - - mutex_lock(&dev->struct_mutex); - drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT); - - dev_priv->agp_initialized = 1; - dev_priv->agp_offset = agp->offset; - mutex_unlock(&dev->struct_mutex); - - DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); - return 0; -} - -int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_fb_t *fb = data; - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - - mutex_lock(&dev->struct_mutex); - drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT); - - dev_priv->vram_initialized = 1; - dev_priv->vram_offset = fb->offset; - - mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); - - return 0; - -} - -int via_final_context(struct drm_device *dev, int context) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - - via_release_futex(dev_priv, context); - - /* Linux specific until context tracking code gets ported to BSD */ - /* Last context, perform cleanup */ - if (list_is_singular(&dev->ctxlist)) { - DRM_DEBUG("Last Context\n"); - drm_legacy_irq_uninstall(dev); - via_cleanup_futex(dev_priv); - via_do_cleanup_map(dev); - } - return 1; -} - -void via_lastclose(struct drm_device *dev) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - - if (!dev_priv) - return; - - mutex_lock(&dev->struct_mutex); - if (dev_priv->vram_initialized) { - drm_mm_takedown(&dev_priv->vram_mm); - dev_priv->vram_initialized = 0; - } - if (dev_priv->agp_initialized) { - drm_mm_takedown(&dev_priv->agp_mm); - dev_priv->agp_initialized = 0; - } - mutex_unlock(&dev->struct_mutex); -} - -int via_mem_alloc(struct drm_device *dev, void *data, - struct drm_file *file) -{ - drm_via_mem_t *mem = data; - int retval = 0, user_key; - struct via_memblock *item; - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - struct via_file_private *file_priv = file->driver_priv; - unsigned long tmpSize; - - if (mem->type > VIA_MEM_AGP) { - DRM_ERROR("Unknown memory type allocation\n"); - return -EINVAL; - } - mutex_lock(&dev->struct_mutex); - if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : - dev_priv->agp_initialized)) { - mutex_unlock(&dev->struct_mutex); - DRM_ERROR - ("Attempt to allocate from uninitialized memory manager.\n"); - return -EINVAL; - } - - item = kzalloc(sizeof(*item), GFP_KERNEL); - if (!item) { - retval = -ENOMEM; - goto fail_alloc; - } - - tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; - if (mem->type == VIA_MEM_AGP) - retval = drm_mm_insert_node(&dev_priv->agp_mm, - &item->mm_node, - tmpSize); - else - retval = drm_mm_insert_node(&dev_priv->vram_mm, - &item->mm_node, - tmpSize); - if (retval) - goto fail_alloc; - - retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL); - if (retval < 0) - goto fail_idr; - user_key = retval; - - list_add(&item->owner_list, &file_priv->obj_list); - mutex_unlock(&dev->struct_mutex); - - mem->offset = ((mem->type == VIA_MEM_VIDEO) ? - dev_priv->vram_offset : dev_priv->agp_offset) + - ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT); - mem->index = user_key; - - return 0; - -fail_idr: - drm_mm_remove_node(&item->mm_node); -fail_alloc: - kfree(item); - mutex_unlock(&dev->struct_mutex); - - mem->offset = 0; - mem->size = 0; - mem->index = 0; - DRM_DEBUG("Video memory allocation failed\n"); - - return retval; -} - -int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_private_t *dev_priv = dev->dev_private; - drm_via_mem_t *mem = data; - struct via_memblock *obj; - - mutex_lock(&dev->struct_mutex); - obj = idr_find(&dev_priv->object_idr, mem->index); - if (obj == NULL) { - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - idr_remove(&dev_priv->object_idr, mem->index); - list_del(&obj->owner_list); - drm_mm_remove_node(&obj->mm_node); - kfree(obj); - mutex_unlock(&dev->struct_mutex); - - DRM_DEBUG("free = 0x%lx\n", mem->index); - - return 0; -} - - -void via_reclaim_buffers_locked(struct drm_device *dev, - struct drm_file *file) -{ - struct via_file_private *file_priv = file->driver_priv; - struct via_memblock *entry, *next; - - if (!(dev->master && file->master->lock.hw_lock)) - return; - - drm_legacy_idlelock_take(&file->master->lock); - - mutex_lock(&dev->struct_mutex); - if (list_empty(&file_priv->obj_list)) { - mutex_unlock(&dev->struct_mutex); - drm_legacy_idlelock_release(&file->master->lock); - - return; - } - - via_driver_dma_quiescent(dev); - - list_for_each_entry_safe(entry, next, &file_priv->obj_list, - owner_list) { - list_del(&entry->owner_list); - drm_mm_remove_node(&entry->mm_node); - kfree(entry); - } - mutex_unlock(&dev->struct_mutex); - - drm_legacy_idlelock_release(&file->master->lock); - - return; -} From e85e4ae0157193703ec8d3ca95c669ddeb2023ee Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:54 +0200 Subject: [PATCH 125/396] drm/via: Embed via_video in via_dri1 All functions are made static as there are no more external users. The file had a new copyright that is kept. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-6-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/via_dri1.c | 66 ++++++++++++++++++++++- drivers/gpu/drm/via/via_drv.h | 4 -- drivers/gpu/drm/via/via_video.c | 94 --------------------------------- 4 files changed, 66 insertions(+), 100 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_video.c diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index daadc0d3233f..398be21c6df8 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_irq.o via_dri1.o via_verifier.o via_video.o via_dmablit.o +via-y := via_irq.o via_dri1.o via_verifier.o via_dmablit.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index 3ebe17649ec2..4c5517330110 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -5,7 +5,8 @@ * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA. * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. All Rights Reserved. * Copyright 2004 The Unichrome project. All Rights Reserved. - * + * Copyright 2005 Thomas Hellstrom. All Rights Reserved. + * * 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 @@ -76,6 +77,69 @@ struct via_memblock { struct list_head owner_list; }; +static void via_init_futex(drm_via_private_t *dev_priv) +{ + unsigned int i; + + DRM_DEBUG("\n"); + + for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { + init_waitqueue_head(&(dev_priv->decoder_queue[i])); + XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0; + } +} + +static void via_cleanup_futex(drm_via_private_t *dev_priv) +{ +} + +static void via_release_futex(drm_via_private_t *dev_priv, int context) +{ + unsigned int i; + volatile int *lock; + + if (!dev_priv->sarea_priv) + return; + + for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { + lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i); + if ((_DRM_LOCKING_CONTEXT(*lock) == context)) { + if (_DRM_LOCK_IS_HELD(*lock) + && (*lock & _DRM_LOCK_CONT)) { + wake_up(&(dev_priv->decoder_queue[i])); + } + *lock = 0; + } + } +} + +static int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_futex_t *fx = data; + volatile int *lock; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + drm_via_sarea_t *sAPriv = dev_priv->sarea_priv; + int ret = 0; + + DRM_DEBUG("\n"); + + if (fx->lock >= VIA_NR_XVMC_LOCKS) + return -EFAULT; + + lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock); + + switch (fx->func) { + case VIA_FUTEX_WAIT: + VIA_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock], + (fx->ms / 10) * (HZ / 100), *lock != fx->val); + return ret; + case VIA_FUTEX_WAKE: + wake_up(&(dev_priv->decoder_queue[fx->lock])); + return 0; + } + return 0; +} + static int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_agp_t *agp = data; diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index c1a5fdf0bc4b..312e86b850f6 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -183,7 +183,6 @@ do { \ remove_wait_queue(&(queue), &entry); \ } while (0) -extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -203,9 +202,6 @@ extern void via_driver_irq_uninstall(struct drm_device *dev); extern int via_dma_cleanup(struct drm_device *dev); extern void via_init_command_verifier(void); extern int via_driver_dma_quiescent(struct drm_device *dev); -extern void via_init_futex(drm_via_private_t *dev_priv); -extern void via_cleanup_futex(drm_via_private_t *dev_priv); -extern void via_release_futex(drm_via_private_t *dev_priv, int context); extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq); extern void via_init_dmablit(struct drm_device *dev); diff --git a/drivers/gpu/drm/via/via_video.c b/drivers/gpu/drm/via/via_video.c deleted file mode 100644 index 53b1f58f99b4..000000000000 --- a/drivers/gpu/drm/via/via_video.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2005 Thomas Hellstrom. All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) 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. - * - * Author: Thomas Hellstrom 2005. - * - * Video and XvMC related functions. - */ - -#include <drm/drm_device.h> -#include <drm/via_drm.h> - -#include "via_drv.h" - -void via_init_futex(drm_via_private_t *dev_priv) -{ - unsigned int i; - - DRM_DEBUG("\n"); - - for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { - init_waitqueue_head(&(dev_priv->decoder_queue[i])); - XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0; - } -} - -void via_cleanup_futex(drm_via_private_t *dev_priv) -{ -} - -void via_release_futex(drm_via_private_t *dev_priv, int context) -{ - unsigned int i; - volatile int *lock; - - if (!dev_priv->sarea_priv) - return; - - for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { - lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i); - if ((_DRM_LOCKING_CONTEXT(*lock) == context)) { - if (_DRM_LOCK_IS_HELD(*lock) - && (*lock & _DRM_LOCK_CONT)) { - wake_up(&(dev_priv->decoder_queue[i])); - } - *lock = 0; - } - } -} - -int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_futex_t *fx = data; - volatile int *lock; - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - drm_via_sarea_t *sAPriv = dev_priv->sarea_priv; - int ret = 0; - - DRM_DEBUG("\n"); - - if (fx->lock >= VIA_NR_XVMC_LOCKS) - return -EFAULT; - - lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock); - - switch (fx->func) { - case VIA_FUTEX_WAIT: - VIA_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock], - (fx->ms / 10) * (HZ / 100), *lock != fx->val); - return ret; - case VIA_FUTEX_WAKE: - wake_up(&(dev_priv->decoder_queue[fx->lock])); - return 0; - } - return 0; -} From b0b3a879258ef43cf15b0bac30b92e7c1c4ebbae Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:55 +0200 Subject: [PATCH 126/396] drm/via: Embed via_irq in via_dri1 All functions are made static as there are no more external users. The file had new copyrights that are kept. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-7-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/via_dri1.c | 347 +++++++++++++++++++++++++++++ drivers/gpu/drm/via/via_drv.h | 9 - drivers/gpu/drm/via/via_irq.c | 388 --------------------------------- 4 files changed, 348 insertions(+), 398 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_irq.c diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index 398be21c6df8..dd75ea8a1423 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_irq.o via_dri1.o via_verifier.o via_dmablit.o +via-y := via_dri1.o via_verifier.o via_dmablit.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index 4c5517330110..32aae172c6f3 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -1,10 +1,12 @@ /* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2002 Tungsten Graphics, Inc. * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. All Rights Reserved. * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA. * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. All Rights Reserved. * Copyright 2004 The Unichrome project. All Rights Reserved. + * Copyright 2004 BEAM Ltd. * Copyright 2005 Thomas Hellstrom. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -77,6 +79,351 @@ struct via_memblock { struct list_head owner_list; }; +#define VIA_REG_INTERRUPT 0x200 + +/* VIA_REG_INTERRUPT */ +#define VIA_IRQ_GLOBAL (1 << 31) +#define VIA_IRQ_VBLANK_ENABLE (1 << 19) +#define VIA_IRQ_VBLANK_PENDING (1 << 3) +#define VIA_IRQ_HQV0_ENABLE (1 << 11) +#define VIA_IRQ_HQV1_ENABLE (1 << 25) +#define VIA_IRQ_HQV0_PENDING (1 << 9) +#define VIA_IRQ_HQV1_PENDING (1 << 10) +#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20) +#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21) +#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22) +#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23) +#define VIA_IRQ_DMA0_DD_PENDING (1 << 4) +#define VIA_IRQ_DMA0_TD_PENDING (1 << 5) +#define VIA_IRQ_DMA1_DD_PENDING (1 << 6) +#define VIA_IRQ_DMA1_TD_PENDING (1 << 7) + +/* + * Device-specific IRQs go here. This type might need to be extended with + * the register if there are multiple IRQ control registers. + * Currently we activate the HQV interrupts of Unichrome Pro group A. + */ + +static maskarray_t via_pro_group_a_irqs[] = { + {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, + 0x00000000 }, + {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, + 0x00000000 }, + {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, + {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, +}; +static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs); +static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; + +static maskarray_t via_unichrome_irqs[] = { + {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, + {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008} +}; +static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs); +static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; + + +static u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe) +{ + drm_via_private_t *dev_priv = dev->dev_private; + + if (pipe != 0) + return 0; + + return atomic_read(&dev_priv->vbl_received); +} + +static irqreturn_t via_driver_irq_handler(int irq, void *arg) +{ + struct drm_device *dev = (struct drm_device *) arg; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + u32 status; + int handled = 0; + ktime_t cur_vblank; + drm_via_irq_t *cur_irq = dev_priv->via_irqs; + int i; + + status = via_read(dev_priv, VIA_REG_INTERRUPT); + if (status & VIA_IRQ_VBLANK_PENDING) { + atomic_inc(&dev_priv->vbl_received); + if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { + cur_vblank = ktime_get(); + if (dev_priv->last_vblank_valid) { + dev_priv->nsec_per_vblank = + ktime_sub(cur_vblank, + dev_priv->last_vblank) >> 4; + } + dev_priv->last_vblank = cur_vblank; + dev_priv->last_vblank_valid = 1; + } + if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { + DRM_DEBUG("nsec per vblank is: %llu\n", + ktime_to_ns(dev_priv->nsec_per_vblank)); + } + drm_handle_vblank(dev, 0); + handled = 1; + } + + for (i = 0; i < dev_priv->num_irqs; ++i) { + if (status & cur_irq->pending_mask) { + atomic_inc(&cur_irq->irq_received); + wake_up(&cur_irq->irq_queue); + handled = 1; + if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) + via_dmablit_handler(dev, 0, 1); + else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) + via_dmablit_handler(dev, 1, 1); + } + cur_irq++; + } + + /* Acknowledge interrupts */ + via_write(dev_priv, VIA_REG_INTERRUPT, status); + + + if (handled) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv) +{ + u32 status; + + if (dev_priv) { + /* Acknowledge interrupts */ + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status | + dev_priv->irq_pending_mask); + } +} + +static int via_enable_vblank(struct drm_device *dev, unsigned int pipe) +{ + drm_via_private_t *dev_priv = dev->dev_private; + u32 status; + + if (pipe != 0) { + DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); + return -EINVAL; + } + + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE); + + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); + + return 0; +} + +static void via_disable_vblank(struct drm_device *dev, unsigned int pipe) +{ + drm_via_private_t *dev_priv = dev->dev_private; + u32 status; + + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE); + + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0); + + if (pipe != 0) + DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); +} + +static int +via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence, + unsigned int *sequence) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + unsigned int cur_irq_sequence; + drm_via_irq_t *cur_irq; + int ret = 0; + maskarray_t *masks; + int real_irq; + + DRM_DEBUG("\n"); + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + if (irq >= drm_via_irq_num) { + DRM_ERROR("Trying to wait on unknown irq %d\n", irq); + return -EINVAL; + } + + real_irq = dev_priv->irq_map[irq]; + + if (real_irq < 0) { + DRM_ERROR("Video IRQ %d not available on this hardware.\n", + irq); + return -EINVAL; + } + + masks = dev_priv->irq_masks; + cur_irq = dev_priv->via_irqs + real_irq; + + if (masks[real_irq][2] && !force_sequence) { + VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, + ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) == + masks[irq][4])); + cur_irq_sequence = atomic_read(&cur_irq->irq_received); + } else { + VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, + (((cur_irq_sequence = + atomic_read(&cur_irq->irq_received)) - + *sequence) <= (1 << 23))); + } + *sequence = cur_irq_sequence; + return ret; +} + + +/* + * drm_dma.h hooks + */ + +static void via_driver_irq_preinstall(struct drm_device *dev) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + u32 status; + drm_via_irq_t *cur_irq; + int i; + + DRM_DEBUG("dev_priv: %p\n", dev_priv); + if (dev_priv) { + cur_irq = dev_priv->via_irqs; + + dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; + dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; + + if (dev_priv->chipset == VIA_PRO_GROUP_A || + dev_priv->chipset == VIA_DX9_0) { + dev_priv->irq_masks = via_pro_group_a_irqs; + dev_priv->num_irqs = via_num_pro_group_a; + dev_priv->irq_map = via_irqmap_pro_group_a; + } else { + dev_priv->irq_masks = via_unichrome_irqs; + dev_priv->num_irqs = via_num_unichrome; + dev_priv->irq_map = via_irqmap_unichrome; + } + + for (i = 0; i < dev_priv->num_irqs; ++i) { + atomic_set(&cur_irq->irq_received, 0); + cur_irq->enable_mask = dev_priv->irq_masks[i][0]; + cur_irq->pending_mask = dev_priv->irq_masks[i][1]; + init_waitqueue_head(&cur_irq->irq_queue); + dev_priv->irq_enable_mask |= cur_irq->enable_mask; + dev_priv->irq_pending_mask |= cur_irq->pending_mask; + cur_irq++; + + DRM_DEBUG("Initializing IRQ %d\n", i); + } + + dev_priv->last_vblank_valid = 0; + + /* Clear VSync interrupt regs */ + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status & + ~(dev_priv->irq_enable_mask)); + + /* Clear bits if they're already high */ + viadrv_acknowledge_irqs(dev_priv); + } +} + +static int via_driver_irq_postinstall(struct drm_device *dev) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + u32 status; + + DRM_DEBUG("fun: %s\n", __func__); + if (!dev_priv) + return -EINVAL; + + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL + | dev_priv->irq_enable_mask); + + /* Some magic, oh for some data sheets ! */ + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); + + return 0; +} + +static void via_driver_irq_uninstall(struct drm_device *dev) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + u32 status; + + DRM_DEBUG("\n"); + if (dev_priv) { + + /* Some more magic, oh for some data sheets ! */ + + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0); + + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status & + ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask)); + } +} + +static int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_irqwait_t *irqwait = data; + struct timespec64 now; + int ret = 0; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + drm_via_irq_t *cur_irq = dev_priv->via_irqs; + int force_sequence; + + if (irqwait->request.irq >= dev_priv->num_irqs) { + DRM_ERROR("Trying to wait on unknown irq %d\n", + irqwait->request.irq); + return -EINVAL; + } + + cur_irq += irqwait->request.irq; + + switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) { + case VIA_IRQ_RELATIVE: + irqwait->request.sequence += + atomic_read(&cur_irq->irq_received); + irqwait->request.type &= ~_DRM_VBLANK_RELATIVE; + break; + case VIA_IRQ_ABSOLUTE: + break; + default: + return -EINVAL; + } + + if (irqwait->request.type & VIA_IRQ_SIGNAL) { + DRM_ERROR("Signals on Via IRQs not implemented yet.\n"); + return -EINVAL; + } + + force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE); + + ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence, + &irqwait->request.sequence); + ktime_get_ts64(&now); + irqwait->reply.tval_sec = now.tv_sec; + irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC; + + return ret; +} + static void via_init_futex(drm_via_private_t *dev_priv) { unsigned int i; diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 312e86b850f6..a1bbe3d5247e 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -183,21 +183,12 @@ do { \ remove_wait_queue(&(queue), &entry); \ } while (0) -extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int via_init_context(struct drm_device *dev, int context); extern int via_do_cleanup_map(struct drm_device *dev); -extern u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe); -extern int via_enable_vblank(struct drm_device *dev, unsigned int pipe); -extern void via_disable_vblank(struct drm_device *dev, unsigned int pipe); - -extern irqreturn_t via_driver_irq_handler(int irq, void *arg); -extern void via_driver_irq_preinstall(struct drm_device *dev); -extern int via_driver_irq_postinstall(struct drm_device *dev); -extern void via_driver_irq_uninstall(struct drm_device *dev); extern int via_dma_cleanup(struct drm_device *dev); extern void via_init_command_verifier(void); diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c deleted file mode 100644 index faeae5d881fb..000000000000 --- a/drivers/gpu/drm/via/via_irq.c +++ /dev/null @@ -1,388 +0,0 @@ -/* via_irq.c - * - * Copyright 2004 BEAM Ltd. - * Copyright 2002 Tungsten Graphics, Inc. - * Copyright 2005 Thomas Hellstrom. - * All Rights Reserved. - * - * 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 - * BEAM LTD, TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. - * - * Authors: - * Terry Barnaby <terry1@beam.ltd.uk> - * Keith Whitwell <keith@tungstengraphics.com> - * Thomas Hellstrom <unichrome@shipmail.org> - * - * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank - * interrupt, as well as an infrastructure to handle other interrupts of the chip. - * The refresh rate is also calculated for video playback sync purposes. - */ - -#include <drm/drm_device.h> -#include <drm/drm_vblank.h> -#include <drm/via_drm.h> - -#include "via_drv.h" - -#define VIA_REG_INTERRUPT 0x200 - -/* VIA_REG_INTERRUPT */ -#define VIA_IRQ_GLOBAL (1 << 31) -#define VIA_IRQ_VBLANK_ENABLE (1 << 19) -#define VIA_IRQ_VBLANK_PENDING (1 << 3) -#define VIA_IRQ_HQV0_ENABLE (1 << 11) -#define VIA_IRQ_HQV1_ENABLE (1 << 25) -#define VIA_IRQ_HQV0_PENDING (1 << 9) -#define VIA_IRQ_HQV1_PENDING (1 << 10) -#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20) -#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21) -#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22) -#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23) -#define VIA_IRQ_DMA0_DD_PENDING (1 << 4) -#define VIA_IRQ_DMA0_TD_PENDING (1 << 5) -#define VIA_IRQ_DMA1_DD_PENDING (1 << 6) -#define VIA_IRQ_DMA1_TD_PENDING (1 << 7) - - -/* - * Device-specific IRQs go here. This type might need to be extended with - * the register if there are multiple IRQ control registers. - * Currently we activate the HQV interrupts of Unichrome Pro group A. - */ - -static maskarray_t via_pro_group_a_irqs[] = { - {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, - 0x00000000 }, - {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, - 0x00000000 }, - {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, - {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, -}; -static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs); -static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; - -static maskarray_t via_unichrome_irqs[] = { - {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, - {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008} -}; -static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs); -static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; - - -u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe) -{ - drm_via_private_t *dev_priv = dev->dev_private; - - if (pipe != 0) - return 0; - - return atomic_read(&dev_priv->vbl_received); -} - -irqreturn_t via_driver_irq_handler(int irq, void *arg) -{ - struct drm_device *dev = (struct drm_device *) arg; - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - u32 status; - int handled = 0; - ktime_t cur_vblank; - drm_via_irq_t *cur_irq = dev_priv->via_irqs; - int i; - - status = via_read(dev_priv, VIA_REG_INTERRUPT); - if (status & VIA_IRQ_VBLANK_PENDING) { - atomic_inc(&dev_priv->vbl_received); - if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { - cur_vblank = ktime_get(); - if (dev_priv->last_vblank_valid) { - dev_priv->nsec_per_vblank = - ktime_sub(cur_vblank, - dev_priv->last_vblank) >> 4; - } - dev_priv->last_vblank = cur_vblank; - dev_priv->last_vblank_valid = 1; - } - if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { - DRM_DEBUG("nsec per vblank is: %llu\n", - ktime_to_ns(dev_priv->nsec_per_vblank)); - } - drm_handle_vblank(dev, 0); - handled = 1; - } - - for (i = 0; i < dev_priv->num_irqs; ++i) { - if (status & cur_irq->pending_mask) { - atomic_inc(&cur_irq->irq_received); - wake_up(&cur_irq->irq_queue); - handled = 1; - if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) - via_dmablit_handler(dev, 0, 1); - else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) - via_dmablit_handler(dev, 1, 1); - } - cur_irq++; - } - - /* Acknowledge interrupts */ - via_write(dev_priv, VIA_REG_INTERRUPT, status); - - - if (handled) - return IRQ_HANDLED; - else - return IRQ_NONE; -} - -static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv) -{ - u32 status; - - if (dev_priv) { - /* Acknowledge interrupts */ - status = via_read(dev_priv, VIA_REG_INTERRUPT); - via_write(dev_priv, VIA_REG_INTERRUPT, status | - dev_priv->irq_pending_mask); - } -} - -int via_enable_vblank(struct drm_device *dev, unsigned int pipe) -{ - drm_via_private_t *dev_priv = dev->dev_private; - u32 status; - - if (pipe != 0) { - DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); - return -EINVAL; - } - - status = via_read(dev_priv, VIA_REG_INTERRUPT); - via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE); - - via_write8(dev_priv, 0x83d4, 0x11); - via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); - - return 0; -} - -void via_disable_vblank(struct drm_device *dev, unsigned int pipe) -{ - drm_via_private_t *dev_priv = dev->dev_private; - u32 status; - - status = via_read(dev_priv, VIA_REG_INTERRUPT); - via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE); - - via_write8(dev_priv, 0x83d4, 0x11); - via_write8_mask(dev_priv, 0x83d5, 0x30, 0); - - if (pipe != 0) - DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); -} - -static int -via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence, - unsigned int *sequence) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - unsigned int cur_irq_sequence; - drm_via_irq_t *cur_irq; - int ret = 0; - maskarray_t *masks; - int real_irq; - - DRM_DEBUG("\n"); - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - if (irq >= drm_via_irq_num) { - DRM_ERROR("Trying to wait on unknown irq %d\n", irq); - return -EINVAL; - } - - real_irq = dev_priv->irq_map[irq]; - - if (real_irq < 0) { - DRM_ERROR("Video IRQ %d not available on this hardware.\n", - irq); - return -EINVAL; - } - - masks = dev_priv->irq_masks; - cur_irq = dev_priv->via_irqs + real_irq; - - if (masks[real_irq][2] && !force_sequence) { - VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, - ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) == - masks[irq][4])); - cur_irq_sequence = atomic_read(&cur_irq->irq_received); - } else { - VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, - (((cur_irq_sequence = - atomic_read(&cur_irq->irq_received)) - - *sequence) <= (1 << 23))); - } - *sequence = cur_irq_sequence; - return ret; -} - - -/* - * drm_dma.h hooks - */ - -void via_driver_irq_preinstall(struct drm_device *dev) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - u32 status; - drm_via_irq_t *cur_irq; - int i; - - DRM_DEBUG("dev_priv: %p\n", dev_priv); - if (dev_priv) { - cur_irq = dev_priv->via_irqs; - - dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; - dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; - - if (dev_priv->chipset == VIA_PRO_GROUP_A || - dev_priv->chipset == VIA_DX9_0) { - dev_priv->irq_masks = via_pro_group_a_irqs; - dev_priv->num_irqs = via_num_pro_group_a; - dev_priv->irq_map = via_irqmap_pro_group_a; - } else { - dev_priv->irq_masks = via_unichrome_irqs; - dev_priv->num_irqs = via_num_unichrome; - dev_priv->irq_map = via_irqmap_unichrome; - } - - for (i = 0; i < dev_priv->num_irqs; ++i) { - atomic_set(&cur_irq->irq_received, 0); - cur_irq->enable_mask = dev_priv->irq_masks[i][0]; - cur_irq->pending_mask = dev_priv->irq_masks[i][1]; - init_waitqueue_head(&cur_irq->irq_queue); - dev_priv->irq_enable_mask |= cur_irq->enable_mask; - dev_priv->irq_pending_mask |= cur_irq->pending_mask; - cur_irq++; - - DRM_DEBUG("Initializing IRQ %d\n", i); - } - - dev_priv->last_vblank_valid = 0; - - /* Clear VSync interrupt regs */ - status = via_read(dev_priv, VIA_REG_INTERRUPT); - via_write(dev_priv, VIA_REG_INTERRUPT, status & - ~(dev_priv->irq_enable_mask)); - - /* Clear bits if they're already high */ - viadrv_acknowledge_irqs(dev_priv); - } -} - -int via_driver_irq_postinstall(struct drm_device *dev) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - u32 status; - - DRM_DEBUG("fun: %s\n", __func__); - if (!dev_priv) - return -EINVAL; - - status = via_read(dev_priv, VIA_REG_INTERRUPT); - via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL - | dev_priv->irq_enable_mask); - - /* Some magic, oh for some data sheets ! */ - via_write8(dev_priv, 0x83d4, 0x11); - via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); - - return 0; -} - -void via_driver_irq_uninstall(struct drm_device *dev) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - u32 status; - - DRM_DEBUG("\n"); - if (dev_priv) { - - /* Some more magic, oh for some data sheets ! */ - - via_write8(dev_priv, 0x83d4, 0x11); - via_write8_mask(dev_priv, 0x83d5, 0x30, 0); - - status = via_read(dev_priv, VIA_REG_INTERRUPT); - via_write(dev_priv, VIA_REG_INTERRUPT, status & - ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask)); - } -} - -int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_irqwait_t *irqwait = data; - struct timespec64 now; - int ret = 0; - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - drm_via_irq_t *cur_irq = dev_priv->via_irqs; - int force_sequence; - - if (irqwait->request.irq >= dev_priv->num_irqs) { - DRM_ERROR("Trying to wait on unknown irq %d\n", - irqwait->request.irq); - return -EINVAL; - } - - cur_irq += irqwait->request.irq; - - switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) { - case VIA_IRQ_RELATIVE: - irqwait->request.sequence += - atomic_read(&cur_irq->irq_received); - irqwait->request.type &= ~_DRM_VBLANK_RELATIVE; - break; - case VIA_IRQ_ABSOLUTE: - break; - default: - return -EINVAL; - } - - if (irqwait->request.type & VIA_IRQ_SIGNAL) { - DRM_ERROR("Signals on Via IRQs not implemented yet.\n"); - return -EINVAL; - } - - force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE); - - ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence, - &irqwait->request.sequence); - ktime_get_ts64(&now); - irqwait->reply.tval_sec = now.tv_sec; - irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC; - - return ret; -} From f99995a4d79b630d39541b1b053f4102f8594caf Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:56 +0200 Subject: [PATCH 127/396] drm/via: Embed via_dmablit in via_dri1 Embed some of the header file in via_drv.h and the rest in via_dri1.c While embedding deleted extra empty lines and functions that has no external users are made static. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-8-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/via_dmablit.c | 807 ------------------------------ drivers/gpu/drm/via/via_dmablit.h | 140 ------ drivers/gpu/drm/via/via_dri1.c | 786 +++++++++++++++++++++++++++++ drivers/gpu/drm/via/via_drv.h | 56 ++- 5 files changed, 835 insertions(+), 956 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_dmablit.c delete mode 100644 drivers/gpu/drm/via/via_dmablit.h diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index dd75ea8a1423..66125b150478 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_dri1.o via_verifier.o via_dmablit.o +via-y := via_dri1.o via_verifier.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c deleted file mode 100644 index e016a4d62090..000000000000 --- a/drivers/gpu/drm/via/via_dmablit.c +++ /dev/null @@ -1,807 +0,0 @@ -/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro - * - * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. - * - * Authors: - * Thomas Hellstrom. - * Partially based on code obtained from Digeo Inc. - */ - - -/* - * Unmaps the DMA mappings. - * FIXME: Is this a NoOp on x86? Also - * FIXME: What happens if this one is called and a pending blit has previously done - * the same DMA mappings? - */ - -#include <linux/pagemap.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> - -#include <drm/drm_device.h> -#include <drm/via_drm.h> - -#include "via_dmablit.h" -#include "via_drv.h" - -#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK) -#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK) -#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT) - -typedef struct _drm_via_descriptor { - uint32_t mem_addr; - uint32_t dev_addr; - uint32_t size; - uint32_t next; -} drm_via_descriptor_t; - - -/* - * Unmap a DMA mapping. - */ - - - -static void -via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg) -{ - int num_desc = vsg->num_desc; - unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page; - unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page; - drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] + - descriptor_this_page; - dma_addr_t next = vsg->chain_start; - - while (num_desc--) { - if (descriptor_this_page-- == 0) { - cur_descriptor_page--; - descriptor_this_page = vsg->descriptors_per_page - 1; - desc_ptr = vsg->desc_pages[cur_descriptor_page] + - descriptor_this_page; - } - dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE); - dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction); - next = (dma_addr_t) desc_ptr->next; - desc_ptr--; - } -} - -/* - * If mode = 0, count how many descriptors are needed. - * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors. - * Descriptors are run in reverse order by the hardware because we are not allowed to update the - * 'next' field without syncing calls when the descriptor is already mapped. - */ - -static void -via_map_blit_for_device(struct pci_dev *pdev, - const drm_via_dmablit_t *xfer, - drm_via_sg_info_t *vsg, - int mode) -{ - unsigned cur_descriptor_page = 0; - unsigned num_descriptors_this_page = 0; - unsigned char *mem_addr = xfer->mem_addr; - unsigned char *cur_mem; - unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr); - uint32_t fb_addr = xfer->fb_addr; - uint32_t cur_fb; - unsigned long line_len; - unsigned remaining_len; - int num_desc = 0; - int cur_line; - dma_addr_t next = 0 | VIA_DMA_DPR_EC; - drm_via_descriptor_t *desc_ptr = NULL; - - if (mode == 1) - desc_ptr = vsg->desc_pages[cur_descriptor_page]; - - for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) { - - line_len = xfer->line_length; - cur_fb = fb_addr; - cur_mem = mem_addr; - - while (line_len > 0) { - - remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len); - line_len -= remaining_len; - - if (mode == 1) { - desc_ptr->mem_addr = - dma_map_page(&pdev->dev, - vsg->pages[VIA_PFN(cur_mem) - - VIA_PFN(first_addr)], - VIA_PGOFF(cur_mem), remaining_len, - vsg->direction); - desc_ptr->dev_addr = cur_fb; - - desc_ptr->size = remaining_len; - desc_ptr->next = (uint32_t) next; - next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), - DMA_TO_DEVICE); - desc_ptr++; - if (++num_descriptors_this_page >= vsg->descriptors_per_page) { - num_descriptors_this_page = 0; - desc_ptr = vsg->desc_pages[++cur_descriptor_page]; - } - } - - num_desc++; - cur_mem += remaining_len; - cur_fb += remaining_len; - } - - mem_addr += xfer->mem_stride; - fb_addr += xfer->fb_stride; - } - - if (mode == 1) { - vsg->chain_start = next; - vsg->state = dr_via_device_mapped; - } - vsg->num_desc = num_desc; -} - -/* - * Function that frees up all resources for a blit. It is usable even if the - * blit info has only been partially built as long as the status enum is consistent - * with the actual status of the used resources. - */ - - -static void -via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) -{ - int i; - - switch (vsg->state) { - case dr_via_device_mapped: - via_unmap_blit_from_device(pdev, vsg); - fallthrough; - case dr_via_desc_pages_alloc: - for (i = 0; i < vsg->num_desc_pages; ++i) { - if (vsg->desc_pages[i] != NULL) - free_page((unsigned long)vsg->desc_pages[i]); - } - kfree(vsg->desc_pages); - fallthrough; - case dr_via_pages_locked: - unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages, - (vsg->direction == DMA_FROM_DEVICE)); - fallthrough; - case dr_via_pages_alloc: - vfree(vsg->pages); - fallthrough; - default: - vsg->state = dr_via_sg_init; - } - vfree(vsg->bounce_buffer); - vsg->bounce_buffer = NULL; - vsg->free_on_sequence = 0; -} - -/* - * Fire a blit engine. - */ - -static void -via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - - via_write(dev_priv, VIA_PCI_DMA_MAR0 + engine*0x10, 0); - via_write(dev_priv, VIA_PCI_DMA_DAR0 + engine*0x10, 0); - via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD | - VIA_DMA_CSR_DE); - via_write(dev_priv, VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); - via_write(dev_priv, VIA_PCI_DMA_BCR0 + engine*0x10, 0); - via_write(dev_priv, VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); - wmb(); - via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); - via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04); -} - -/* - * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will - * occur here if the calling user does not have access to the submitted address. - */ - -static int -via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) -{ - int ret; - unsigned long first_pfn = VIA_PFN(xfer->mem_addr); - vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride - 1)) - - first_pfn + 1; - - vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages)); - if (NULL == vsg->pages) - return -ENOMEM; - ret = pin_user_pages_fast((unsigned long)xfer->mem_addr, - vsg->num_pages, - vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0, - vsg->pages); - if (ret != vsg->num_pages) { - if (ret < 0) - return ret; - vsg->state = dr_via_pages_locked; - return -EINVAL; - } - vsg->state = dr_via_pages_locked; - DRM_DEBUG("DMA pages locked\n"); - return 0; -} - -/* - * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the - * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be - * quite large for some blits, and pages don't need to be contiguous. - */ - -static int -via_alloc_desc_pages(drm_via_sg_info_t *vsg) -{ - int i; - - vsg->descriptors_per_page = PAGE_SIZE / sizeof(drm_via_descriptor_t); - vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) / - vsg->descriptors_per_page; - - if (NULL == (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL))) - return -ENOMEM; - - vsg->state = dr_via_desc_pages_alloc; - for (i = 0; i < vsg->num_desc_pages; ++i) { - if (NULL == (vsg->desc_pages[i] = - (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL))) - return -ENOMEM; - } - DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages, - vsg->num_desc); - return 0; -} - -static void -via_abort_dmablit(struct drm_device *dev, int engine) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - - via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA); -} - -static void -via_dmablit_engine_off(struct drm_device *dev, int engine) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - - via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD); -} - - - -/* - * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here. - * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue - * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while - * the workqueue task takes care of processing associated with the old blit. - */ - -void -via_dmablit_handler(struct drm_device *dev, int engine, int from_irq) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - drm_via_blitq_t *blitq = dev_priv->blit_queues + engine; - int cur; - int done_transfer; - unsigned long irqsave = 0; - uint32_t status = 0; - - DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n", - engine, from_irq, (unsigned long) blitq); - - if (from_irq) - spin_lock(&blitq->blit_lock); - else - spin_lock_irqsave(&blitq->blit_lock, irqsave); - - done_transfer = blitq->is_active && - ((status = via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD); - done_transfer = done_transfer || (blitq->aborting && !(status & VIA_DMA_CSR_DE)); - - cur = blitq->cur; - if (done_transfer) { - - blitq->blits[cur]->aborted = blitq->aborting; - blitq->done_blit_handle++; - wake_up(blitq->blit_queue + cur); - - cur++; - if (cur >= VIA_NUM_BLIT_SLOTS) - cur = 0; - blitq->cur = cur; - - /* - * Clear transfer done flag. - */ - - via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD); - - blitq->is_active = 0; - blitq->aborting = 0; - schedule_work(&blitq->wq); - - } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) { - - /* - * Abort transfer after one second. - */ - - via_abort_dmablit(dev, engine); - blitq->aborting = 1; - blitq->end = jiffies + HZ; - } - - if (!blitq->is_active) { - if (blitq->num_outstanding) { - via_fire_dmablit(dev, blitq->blits[cur], engine); - blitq->is_active = 1; - blitq->cur = cur; - blitq->num_outstanding--; - blitq->end = jiffies + HZ; - if (!timer_pending(&blitq->poll_timer)) - mod_timer(&blitq->poll_timer, jiffies + 1); - } else { - if (timer_pending(&blitq->poll_timer)) - del_timer(&blitq->poll_timer); - via_dmablit_engine_off(dev, engine); - } - } - - if (from_irq) - spin_unlock(&blitq->blit_lock); - else - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); -} - - - -/* - * Check whether this blit is still active, performing necessary locking. - */ - -static int -via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue) -{ - unsigned long irqsave; - uint32_t slot; - int active; - - spin_lock_irqsave(&blitq->blit_lock, irqsave); - - /* - * Allow for handle wraparounds. - */ - - active = ((blitq->done_blit_handle - handle) > (1 << 23)) && - ((blitq->cur_blit_handle - handle) <= (1 << 23)); - - if (queue && active) { - slot = handle - blitq->done_blit_handle + blitq->cur - 1; - if (slot >= VIA_NUM_BLIT_SLOTS) - slot -= VIA_NUM_BLIT_SLOTS; - *queue = blitq->blit_queue + slot; - } - - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - - return active; -} - -/* - * Sync. Wait for at least three seconds for the blit to be performed. - */ - -static int -via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine) -{ - - drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - drm_via_blitq_t *blitq = dev_priv->blit_queues + engine; - wait_queue_head_t *queue; - int ret = 0; - - if (via_dmablit_active(blitq, engine, handle, &queue)) { - VIA_WAIT_ON(ret, *queue, 3 * HZ, - !via_dmablit_active(blitq, engine, handle, NULL)); - } - DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n", - handle, engine, ret); - - return ret; -} - - -/* - * A timer that regularly polls the blit engine in cases where we don't have interrupts: - * a) Broken hardware (typically those that don't have any video capture facility). - * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted. - * The timer and hardware IRQ's can and do work in parallel. If the hardware has - * irqs, it will shorten the latency somewhat. - */ - - - -static void -via_dmablit_timer(struct timer_list *t) -{ - drm_via_blitq_t *blitq = from_timer(blitq, t, poll_timer); - struct drm_device *dev = blitq->dev; - int engine = (int) - (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues); - - DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine, - (unsigned long) jiffies); - - via_dmablit_handler(dev, engine, 0); - - if (!timer_pending(&blitq->poll_timer)) { - mod_timer(&blitq->poll_timer, jiffies + 1); - - /* - * Rerun handler to delete timer if engines are off, and - * to shorten abort latency. This is a little nasty. - */ - - via_dmablit_handler(dev, engine, 0); - - } -} - - - - -/* - * Workqueue task that frees data and mappings associated with a blit. - * Also wakes up waiting processes. Each of these tasks handles one - * blit engine only and may not be called on each interrupt. - */ - - -static void -via_dmablit_workqueue(struct work_struct *work) -{ - drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq); - struct drm_device *dev = blitq->dev; - struct pci_dev *pdev = to_pci_dev(dev->dev); - unsigned long irqsave; - drm_via_sg_info_t *cur_sg; - int cur_released; - - - DRM_DEBUG("Workqueue task called for blit engine %ld\n", (unsigned long) - (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues)); - - spin_lock_irqsave(&blitq->blit_lock, irqsave); - - while (blitq->serviced != blitq->cur) { - - cur_released = blitq->serviced++; - - DRM_DEBUG("Releasing blit slot %d\n", cur_released); - - if (blitq->serviced >= VIA_NUM_BLIT_SLOTS) - blitq->serviced = 0; - - cur_sg = blitq->blits[cur_released]; - blitq->num_free++; - - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - - wake_up(&blitq->busy_queue); - - via_free_sg_info(pdev, cur_sg); - kfree(cur_sg); - - spin_lock_irqsave(&blitq->blit_lock, irqsave); - } - - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); -} - - -/* - * Init all blit engines. Currently we use two, but some hardware have 4. - */ - - -void -via_init_dmablit(struct drm_device *dev) -{ - int i, j; - drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - struct pci_dev *pdev = to_pci_dev(dev->dev); - drm_via_blitq_t *blitq; - - pci_set_master(pdev); - - for (i = 0; i < VIA_NUM_BLIT_ENGINES; ++i) { - blitq = dev_priv->blit_queues + i; - blitq->dev = dev; - blitq->cur_blit_handle = 0; - blitq->done_blit_handle = 0; - blitq->head = 0; - blitq->cur = 0; - blitq->serviced = 0; - blitq->num_free = VIA_NUM_BLIT_SLOTS - 1; - blitq->num_outstanding = 0; - blitq->is_active = 0; - blitq->aborting = 0; - spin_lock_init(&blitq->blit_lock); - for (j = 0; j < VIA_NUM_BLIT_SLOTS; ++j) - init_waitqueue_head(blitq->blit_queue + j); - init_waitqueue_head(&blitq->busy_queue); - INIT_WORK(&blitq->wq, via_dmablit_workqueue); - timer_setup(&blitq->poll_timer, via_dmablit_timer, 0); - } -} - -/* - * Build all info and do all mappings required for a blit. - */ - - -static int -via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) -{ - struct pci_dev *pdev = to_pci_dev(dev->dev); - int draw = xfer->to_fb; - int ret = 0; - - vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - vsg->bounce_buffer = NULL; - - vsg->state = dr_via_sg_init; - - if (xfer->num_lines <= 0 || xfer->line_length <= 0) { - DRM_ERROR("Zero size bitblt.\n"); - return -EINVAL; - } - - /* - * Below check is a driver limitation, not a hardware one. We - * don't want to lock unused pages, and don't want to incoporate the - * extra logic of avoiding them. Make sure there are no. - * (Not a big limitation anyway.) - */ - - if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) { - DRM_ERROR("Too large system memory stride. Stride: %d, " - "Length: %d\n", xfer->mem_stride, xfer->line_length); - return -EINVAL; - } - - if ((xfer->mem_stride == xfer->line_length) && - (xfer->fb_stride == xfer->line_length)) { - xfer->mem_stride *= xfer->num_lines; - xfer->line_length = xfer->mem_stride; - xfer->fb_stride = xfer->mem_stride; - xfer->num_lines = 1; - } - - /* - * Don't lock an arbitrary large number of pages, since that causes a - * DOS security hole. - */ - - if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) { - DRM_ERROR("Too large PCI DMA bitblt.\n"); - return -EINVAL; - } - - /* - * we allow a negative fb stride to allow flipping of images in - * transfer. - */ - - if (xfer->mem_stride < xfer->line_length || - abs(xfer->fb_stride) < xfer->line_length) { - DRM_ERROR("Invalid frame-buffer / memory stride.\n"); - return -EINVAL; - } - - /* - * A hardware bug seems to be worked around if system memory addresses start on - * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted - * about this. Meanwhile, impose the following restrictions: - */ - -#ifdef VIA_BUGFREE - if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) || - ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) { - DRM_ERROR("Invalid DRM bitblt alignment.\n"); - return -EINVAL; - } -#else - if ((((unsigned long)xfer->mem_addr & 15) || - ((unsigned long)xfer->fb_addr & 3)) || - ((xfer->num_lines > 1) && - ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) { - DRM_ERROR("Invalid DRM bitblt alignment.\n"); - return -EINVAL; - } -#endif - - if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) { - DRM_ERROR("Could not lock DMA pages.\n"); - via_free_sg_info(pdev, vsg); - return ret; - } - - via_map_blit_for_device(pdev, xfer, vsg, 0); - if (0 != (ret = via_alloc_desc_pages(vsg))) { - DRM_ERROR("Could not allocate DMA descriptor pages.\n"); - via_free_sg_info(pdev, vsg); - return ret; - } - via_map_blit_for_device(pdev, xfer, vsg, 1); - - return 0; -} - - -/* - * Reserve one free slot in the blit queue. Will wait for one second for one - * to become available. Otherwise -EBUSY is returned. - */ - -static int -via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine) -{ - int ret = 0; - unsigned long irqsave; - - DRM_DEBUG("Num free is %d\n", blitq->num_free); - spin_lock_irqsave(&blitq->blit_lock, irqsave); - while (blitq->num_free == 0) { - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - - VIA_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0); - if (ret) - return (-EINTR == ret) ? -EAGAIN : ret; - - spin_lock_irqsave(&blitq->blit_lock, irqsave); - } - - blitq->num_free--; - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - - return 0; -} - -/* - * Hand back a free slot if we changed our mind. - */ - -static void -via_dmablit_release_slot(drm_via_blitq_t *blitq) -{ - unsigned long irqsave; - - spin_lock_irqsave(&blitq->blit_lock, irqsave); - blitq->num_free++; - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - wake_up(&blitq->busy_queue); -} - -/* - * Grab a free slot. Build blit info and queue a blit. - */ - - -static int -via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - drm_via_sg_info_t *vsg; - drm_via_blitq_t *blitq; - int ret; - int engine; - unsigned long irqsave; - - if (dev_priv == NULL) { - DRM_ERROR("Called without initialization.\n"); - return -EINVAL; - } - - engine = (xfer->to_fb) ? 0 : 1; - blitq = dev_priv->blit_queues + engine; - if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) - return ret; - if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) { - via_dmablit_release_slot(blitq); - return -ENOMEM; - } - if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) { - via_dmablit_release_slot(blitq); - kfree(vsg); - return ret; - } - spin_lock_irqsave(&blitq->blit_lock, irqsave); - - blitq->blits[blitq->head++] = vsg; - if (blitq->head >= VIA_NUM_BLIT_SLOTS) - blitq->head = 0; - blitq->num_outstanding++; - xfer->sync.sync_handle = ++blitq->cur_blit_handle; - - spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - xfer->sync.engine = engine; - - via_dmablit_handler(dev, engine, 0); - - return 0; -} - -/* - * Sync on a previously submitted blit. Note that the X server use signals extensively, and - * that there is a very big probability that this IOCTL will be interrupted by a signal. In that - * case it returns with -EAGAIN for the signal to be delivered. - * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock(). - */ - -int -via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_blitsync_t *sync = data; - int err; - - if (sync->engine >= VIA_NUM_BLIT_ENGINES) - return -EINVAL; - - err = via_dmablit_sync(dev, sync->sync_handle, sync->engine); - - if (-EINTR == err) - err = -EAGAIN; - - return err; -} - - -/* - * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal - * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should - * be reissued. See the above IOCTL code. - */ - -int -via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_via_dmablit_t *xfer = data; - int err; - - err = via_dmablit(dev, xfer); - - return err; -} diff --git a/drivers/gpu/drm/via/via_dmablit.h b/drivers/gpu/drm/via/via_dmablit.h deleted file mode 100644 index 9b662a327cef..000000000000 --- a/drivers/gpu/drm/via/via_dmablit.h +++ /dev/null @@ -1,140 +0,0 @@ -/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro - * - * Copyright 2005 Thomas Hellstrom. - * All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. - * - * Authors: - * Thomas Hellstrom. - * Register info from Digeo Inc. - */ - -#ifndef _VIA_DMABLIT_H -#define _VIA_DMABLIT_H - -#include <linux/dma-mapping.h> - -#define VIA_NUM_BLIT_ENGINES 2 -#define VIA_NUM_BLIT_SLOTS 8 - -struct _drm_via_descriptor; - -typedef struct _drm_via_sg_info { - struct page **pages; - unsigned long num_pages; - struct _drm_via_descriptor **desc_pages; - int num_desc_pages; - int num_desc; - enum dma_data_direction direction; - unsigned char *bounce_buffer; - dma_addr_t chain_start; - uint32_t free_on_sequence; - unsigned int descriptors_per_page; - int aborted; - enum { - dr_via_device_mapped, - dr_via_desc_pages_alloc, - dr_via_pages_locked, - dr_via_pages_alloc, - dr_via_sg_init - } state; -} drm_via_sg_info_t; - -typedef struct _drm_via_blitq { - struct drm_device *dev; - uint32_t cur_blit_handle; - uint32_t done_blit_handle; - unsigned serviced; - unsigned head; - unsigned cur; - unsigned num_free; - unsigned num_outstanding; - unsigned long end; - int aborting; - int is_active; - drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS]; - spinlock_t blit_lock; - wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS]; - wait_queue_head_t busy_queue; - struct work_struct wq; - struct timer_list poll_timer; -} drm_via_blitq_t; - - -/* - * PCI DMA Registers - * Channels 2 & 3 don't seem to be implemented in hardware. - */ - -#define VIA_PCI_DMA_MAR0 0xE40 /* Memory Address Register of Channel 0 */ -#define VIA_PCI_DMA_DAR0 0xE44 /* Device Address Register of Channel 0 */ -#define VIA_PCI_DMA_BCR0 0xE48 /* Byte Count Register of Channel 0 */ -#define VIA_PCI_DMA_DPR0 0xE4C /* Descriptor Pointer Register of Channel 0 */ - -#define VIA_PCI_DMA_MAR1 0xE50 /* Memory Address Register of Channel 1 */ -#define VIA_PCI_DMA_DAR1 0xE54 /* Device Address Register of Channel 1 */ -#define VIA_PCI_DMA_BCR1 0xE58 /* Byte Count Register of Channel 1 */ -#define VIA_PCI_DMA_DPR1 0xE5C /* Descriptor Pointer Register of Channel 1 */ - -#define VIA_PCI_DMA_MAR2 0xE60 /* Memory Address Register of Channel 2 */ -#define VIA_PCI_DMA_DAR2 0xE64 /* Device Address Register of Channel 2 */ -#define VIA_PCI_DMA_BCR2 0xE68 /* Byte Count Register of Channel 2 */ -#define VIA_PCI_DMA_DPR2 0xE6C /* Descriptor Pointer Register of Channel 2 */ - -#define VIA_PCI_DMA_MAR3 0xE70 /* Memory Address Register of Channel 3 */ -#define VIA_PCI_DMA_DAR3 0xE74 /* Device Address Register of Channel 3 */ -#define VIA_PCI_DMA_BCR3 0xE78 /* Byte Count Register of Channel 3 */ -#define VIA_PCI_DMA_DPR3 0xE7C /* Descriptor Pointer Register of Channel 3 */ - -#define VIA_PCI_DMA_MR0 0xE80 /* Mode Register of Channel 0 */ -#define VIA_PCI_DMA_MR1 0xE84 /* Mode Register of Channel 1 */ -#define VIA_PCI_DMA_MR2 0xE88 /* Mode Register of Channel 2 */ -#define VIA_PCI_DMA_MR3 0xE8C /* Mode Register of Channel 3 */ - -#define VIA_PCI_DMA_CSR0 0xE90 /* Command/Status Register of Channel 0 */ -#define VIA_PCI_DMA_CSR1 0xE94 /* Command/Status Register of Channel 1 */ -#define VIA_PCI_DMA_CSR2 0xE98 /* Command/Status Register of Channel 2 */ -#define VIA_PCI_DMA_CSR3 0xE9C /* Command/Status Register of Channel 3 */ - -#define VIA_PCI_DMA_PTR 0xEA0 /* Priority Type Register */ - -/* Define for DMA engine */ -/* DPR */ -#define VIA_DMA_DPR_EC (1<<1) /* end of chain */ -#define VIA_DMA_DPR_DDIE (1<<2) /* descriptor done interrupt enable */ -#define VIA_DMA_DPR_DT (1<<3) /* direction of transfer (RO) */ - -/* MR */ -#define VIA_DMA_MR_CM (1<<0) /* chaining mode */ -#define VIA_DMA_MR_TDIE (1<<1) /* transfer done interrupt enable */ -#define VIA_DMA_MR_HENDMACMD (1<<7) /* ? */ - -/* CSR */ -#define VIA_DMA_CSR_DE (1<<0) /* DMA enable */ -#define VIA_DMA_CSR_TS (1<<1) /* transfer start */ -#define VIA_DMA_CSR_TA (1<<2) /* transfer abort */ -#define VIA_DMA_CSR_TD (1<<3) /* transfer done */ -#define VIA_DMA_CSR_DD (1<<4) /* descriptor done */ -#define VIA_DMA_DPR_EC (1<<1) /* end of chain */ - - - -#endif diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index 32aae172c6f3..f8b1f837feb1 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -32,6 +32,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/vmalloc.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> @@ -98,6 +99,62 @@ struct via_memblock { #define VIA_IRQ_DMA1_DD_PENDING (1 << 6) #define VIA_IRQ_DMA1_TD_PENDING (1 << 7) +/* + * PCI DMA Registers + * Channels 2 & 3 don't seem to be implemented in hardware. + */ + +#define VIA_PCI_DMA_MAR0 0xE40 /* Memory Address Register of Channel 0 */ +#define VIA_PCI_DMA_DAR0 0xE44 /* Device Address Register of Channel 0 */ +#define VIA_PCI_DMA_BCR0 0xE48 /* Byte Count Register of Channel 0 */ +#define VIA_PCI_DMA_DPR0 0xE4C /* Descriptor Pointer Register of Channel 0 */ + +#define VIA_PCI_DMA_MAR1 0xE50 /* Memory Address Register of Channel 1 */ +#define VIA_PCI_DMA_DAR1 0xE54 /* Device Address Register of Channel 1 */ +#define VIA_PCI_DMA_BCR1 0xE58 /* Byte Count Register of Channel 1 */ +#define VIA_PCI_DMA_DPR1 0xE5C /* Descriptor Pointer Register of Channel 1 */ + +#define VIA_PCI_DMA_MAR2 0xE60 /* Memory Address Register of Channel 2 */ +#define VIA_PCI_DMA_DAR2 0xE64 /* Device Address Register of Channel 2 */ +#define VIA_PCI_DMA_BCR2 0xE68 /* Byte Count Register of Channel 2 */ +#define VIA_PCI_DMA_DPR2 0xE6C /* Descriptor Pointer Register of Channel 2 */ + +#define VIA_PCI_DMA_MAR3 0xE70 /* Memory Address Register of Channel 3 */ +#define VIA_PCI_DMA_DAR3 0xE74 /* Device Address Register of Channel 3 */ +#define VIA_PCI_DMA_BCR3 0xE78 /* Byte Count Register of Channel 3 */ +#define VIA_PCI_DMA_DPR3 0xE7C /* Descriptor Pointer Register of Channel 3 */ + +#define VIA_PCI_DMA_MR0 0xE80 /* Mode Register of Channel 0 */ +#define VIA_PCI_DMA_MR1 0xE84 /* Mode Register of Channel 1 */ +#define VIA_PCI_DMA_MR2 0xE88 /* Mode Register of Channel 2 */ +#define VIA_PCI_DMA_MR3 0xE8C /* Mode Register of Channel 3 */ + +#define VIA_PCI_DMA_CSR0 0xE90 /* Command/Status Register of Channel 0 */ +#define VIA_PCI_DMA_CSR1 0xE94 /* Command/Status Register of Channel 1 */ +#define VIA_PCI_DMA_CSR2 0xE98 /* Command/Status Register of Channel 2 */ +#define VIA_PCI_DMA_CSR3 0xE9C /* Command/Status Register of Channel 3 */ + +#define VIA_PCI_DMA_PTR 0xEA0 /* Priority Type Register */ + +/* Define for DMA engine */ +/* DPR */ +#define VIA_DMA_DPR_EC (1<<1) /* end of chain */ +#define VIA_DMA_DPR_DDIE (1<<2) /* descriptor done interrupt enable */ +#define VIA_DMA_DPR_DT (1<<3) /* direction of transfer (RO) */ + +/* MR */ +#define VIA_DMA_MR_CM (1<<0) /* chaining mode */ +#define VIA_DMA_MR_TDIE (1<<1) /* transfer done interrupt enable */ +#define VIA_DMA_MR_HENDMACMD (1<<7) /* ? */ + +/* CSR */ +#define VIA_DMA_CSR_DE (1<<0) /* DMA enable */ +#define VIA_DMA_CSR_TS (1<<1) /* transfer start */ +#define VIA_DMA_CSR_TA (1<<2) /* transfer abort */ +#define VIA_DMA_CSR_TD (1<<3) /* transfer done */ +#define VIA_DMA_CSR_DD (1<<4) /* descriptor done */ +#define VIA_DMA_DPR_EC (1<<1) /* end of chain */ + /* * Device-specific IRQs go here. This type might need to be extended with * the register if there are multiple IRQ control registers. @@ -127,6 +184,735 @@ static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs); static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; +/* + * Unmaps the DMA mappings. + * FIXME: Is this a NoOp on x86? Also + * FIXME: What happens if this one is called and a pending blit has previously done + * the same DMA mappings? + */ +#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK) +#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK) +#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT) + +typedef struct _drm_via_descriptor { + uint32_t mem_addr; + uint32_t dev_addr; + uint32_t size; + uint32_t next; +} drm_via_descriptor_t; + + +/* + * Unmap a DMA mapping. + */ +static void +via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg) +{ + int num_desc = vsg->num_desc; + unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page; + unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page; + drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] + + descriptor_this_page; + dma_addr_t next = vsg->chain_start; + + while (num_desc--) { + if (descriptor_this_page-- == 0) { + cur_descriptor_page--; + descriptor_this_page = vsg->descriptors_per_page - 1; + desc_ptr = vsg->desc_pages[cur_descriptor_page] + + descriptor_this_page; + } + dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE); + dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction); + next = (dma_addr_t) desc_ptr->next; + desc_ptr--; + } +} + +/* + * If mode = 0, count how many descriptors are needed. + * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors. + * Descriptors are run in reverse order by the hardware because we are not allowed to update the + * 'next' field without syncing calls when the descriptor is already mapped. + */ +static void +via_map_blit_for_device(struct pci_dev *pdev, + const drm_via_dmablit_t *xfer, + drm_via_sg_info_t *vsg, + int mode) +{ + unsigned cur_descriptor_page = 0; + unsigned num_descriptors_this_page = 0; + unsigned char *mem_addr = xfer->mem_addr; + unsigned char *cur_mem; + unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr); + uint32_t fb_addr = xfer->fb_addr; + uint32_t cur_fb; + unsigned long line_len; + unsigned remaining_len; + int num_desc = 0; + int cur_line; + dma_addr_t next = 0 | VIA_DMA_DPR_EC; + drm_via_descriptor_t *desc_ptr = NULL; + + if (mode == 1) + desc_ptr = vsg->desc_pages[cur_descriptor_page]; + + for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) { + + line_len = xfer->line_length; + cur_fb = fb_addr; + cur_mem = mem_addr; + + while (line_len > 0) { + + remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len); + line_len -= remaining_len; + + if (mode == 1) { + desc_ptr->mem_addr = + dma_map_page(&pdev->dev, + vsg->pages[VIA_PFN(cur_mem) - + VIA_PFN(first_addr)], + VIA_PGOFF(cur_mem), remaining_len, + vsg->direction); + desc_ptr->dev_addr = cur_fb; + + desc_ptr->size = remaining_len; + desc_ptr->next = (uint32_t) next; + next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), + DMA_TO_DEVICE); + desc_ptr++; + if (++num_descriptors_this_page >= vsg->descriptors_per_page) { + num_descriptors_this_page = 0; + desc_ptr = vsg->desc_pages[++cur_descriptor_page]; + } + } + + num_desc++; + cur_mem += remaining_len; + cur_fb += remaining_len; + } + + mem_addr += xfer->mem_stride; + fb_addr += xfer->fb_stride; + } + + if (mode == 1) { + vsg->chain_start = next; + vsg->state = dr_via_device_mapped; + } + vsg->num_desc = num_desc; +} + +/* + * Function that frees up all resources for a blit. It is usable even if the + * blit info has only been partially built as long as the status enum is consistent + * with the actual status of the used resources. + */ +static void +via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) +{ + int i; + + switch (vsg->state) { + case dr_via_device_mapped: + via_unmap_blit_from_device(pdev, vsg); + fallthrough; + case dr_via_desc_pages_alloc: + for (i = 0; i < vsg->num_desc_pages; ++i) { + if (vsg->desc_pages[i] != NULL) + free_page((unsigned long)vsg->desc_pages[i]); + } + kfree(vsg->desc_pages); + fallthrough; + case dr_via_pages_locked: + unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages, + (vsg->direction == DMA_FROM_DEVICE)); + fallthrough; + case dr_via_pages_alloc: + vfree(vsg->pages); + fallthrough; + default: + vsg->state = dr_via_sg_init; + } + vfree(vsg->bounce_buffer); + vsg->bounce_buffer = NULL; + vsg->free_on_sequence = 0; +} + +/* + * Fire a blit engine. + */ +static void +via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; + + via_write(dev_priv, VIA_PCI_DMA_MAR0 + engine*0x10, 0); + via_write(dev_priv, VIA_PCI_DMA_DAR0 + engine*0x10, 0); + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD | + VIA_DMA_CSR_DE); + via_write(dev_priv, VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); + via_write(dev_priv, VIA_PCI_DMA_BCR0 + engine*0x10, 0); + via_write(dev_priv, VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); + wmb(); + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); + via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04); +} + +/* + * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will + * occur here if the calling user does not have access to the submitted address. + */ +static int +via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) +{ + int ret; + unsigned long first_pfn = VIA_PFN(xfer->mem_addr); + vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride - 1)) - + first_pfn + 1; + + vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages)); + if (NULL == vsg->pages) + return -ENOMEM; + ret = pin_user_pages_fast((unsigned long)xfer->mem_addr, + vsg->num_pages, + vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0, + vsg->pages); + if (ret != vsg->num_pages) { + if (ret < 0) + return ret; + vsg->state = dr_via_pages_locked; + return -EINVAL; + } + vsg->state = dr_via_pages_locked; + DRM_DEBUG("DMA pages locked\n"); + return 0; +} + +/* + * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the + * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be + * quite large for some blits, and pages don't need to be contiguous. + */ +static int +via_alloc_desc_pages(drm_via_sg_info_t *vsg) +{ + int i; + + vsg->descriptors_per_page = PAGE_SIZE / sizeof(drm_via_descriptor_t); + vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) / + vsg->descriptors_per_page; + + if (NULL == (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL))) + return -ENOMEM; + + vsg->state = dr_via_desc_pages_alloc; + for (i = 0; i < vsg->num_desc_pages; ++i) { + if (NULL == (vsg->desc_pages[i] = + (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL))) + return -ENOMEM; + } + DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages, + vsg->num_desc); + return 0; +} + +static void +via_abort_dmablit(struct drm_device *dev, int engine) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; + + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA); +} + +static void +via_dmablit_engine_off(struct drm_device *dev, int engine) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; + + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD); +} + +/* + * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here. + * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue + * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while + * the workqueue task takes care of processing associated with the old blit. + */ +static void +via_dmablit_handler(struct drm_device *dev, int engine, int from_irq) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; + drm_via_blitq_t *blitq = dev_priv->blit_queues + engine; + int cur; + int done_transfer; + unsigned long irqsave = 0; + uint32_t status = 0; + + DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n", + engine, from_irq, (unsigned long) blitq); + + if (from_irq) + spin_lock(&blitq->blit_lock); + else + spin_lock_irqsave(&blitq->blit_lock, irqsave); + + done_transfer = blitq->is_active && + ((status = via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD); + done_transfer = done_transfer || (blitq->aborting && !(status & VIA_DMA_CSR_DE)); + + cur = blitq->cur; + if (done_transfer) { + + blitq->blits[cur]->aborted = blitq->aborting; + blitq->done_blit_handle++; + wake_up(blitq->blit_queue + cur); + + cur++; + if (cur >= VIA_NUM_BLIT_SLOTS) + cur = 0; + blitq->cur = cur; + + /* + * Clear transfer done flag. + */ + + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD); + + blitq->is_active = 0; + blitq->aborting = 0; + schedule_work(&blitq->wq); + + } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) { + + /* + * Abort transfer after one second. + */ + + via_abort_dmablit(dev, engine); + blitq->aborting = 1; + blitq->end = jiffies + HZ; + } + + if (!blitq->is_active) { + if (blitq->num_outstanding) { + via_fire_dmablit(dev, blitq->blits[cur], engine); + blitq->is_active = 1; + blitq->cur = cur; + blitq->num_outstanding--; + blitq->end = jiffies + HZ; + if (!timer_pending(&blitq->poll_timer)) + mod_timer(&blitq->poll_timer, jiffies + 1); + } else { + if (timer_pending(&blitq->poll_timer)) + del_timer(&blitq->poll_timer); + via_dmablit_engine_off(dev, engine); + } + } + + if (from_irq) + spin_unlock(&blitq->blit_lock); + else + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); +} + +/* + * Check whether this blit is still active, performing necessary locking. + */ +static int +via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue) +{ + unsigned long irqsave; + uint32_t slot; + int active; + + spin_lock_irqsave(&blitq->blit_lock, irqsave); + + /* + * Allow for handle wraparounds. + */ + + active = ((blitq->done_blit_handle - handle) > (1 << 23)) && + ((blitq->cur_blit_handle - handle) <= (1 << 23)); + + if (queue && active) { + slot = handle - blitq->done_blit_handle + blitq->cur - 1; + if (slot >= VIA_NUM_BLIT_SLOTS) + slot -= VIA_NUM_BLIT_SLOTS; + *queue = blitq->blit_queue + slot; + } + + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); + + return active; +} + +/* + * Sync. Wait for at least three seconds for the blit to be performed. + */ +static int +via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine) +{ + + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; + drm_via_blitq_t *blitq = dev_priv->blit_queues + engine; + wait_queue_head_t *queue; + int ret = 0; + + if (via_dmablit_active(blitq, engine, handle, &queue)) { + VIA_WAIT_ON(ret, *queue, 3 * HZ, + !via_dmablit_active(blitq, engine, handle, NULL)); + } + DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n", + handle, engine, ret); + + return ret; +} + +/* + * A timer that regularly polls the blit engine in cases where we don't have interrupts: + * a) Broken hardware (typically those that don't have any video capture facility). + * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted. + * The timer and hardware IRQ's can and do work in parallel. If the hardware has + * irqs, it will shorten the latency somewhat. + */ +static void +via_dmablit_timer(struct timer_list *t) +{ + drm_via_blitq_t *blitq = from_timer(blitq, t, poll_timer); + struct drm_device *dev = blitq->dev; + int engine = (int) + (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues); + + DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine, + (unsigned long) jiffies); + + via_dmablit_handler(dev, engine, 0); + + if (!timer_pending(&blitq->poll_timer)) { + mod_timer(&blitq->poll_timer, jiffies + 1); + + /* + * Rerun handler to delete timer if engines are off, and + * to shorten abort latency. This is a little nasty. + */ + + via_dmablit_handler(dev, engine, 0); + + } +} + +/* + * Workqueue task that frees data and mappings associated with a blit. + * Also wakes up waiting processes. Each of these tasks handles one + * blit engine only and may not be called on each interrupt. + */ +static void +via_dmablit_workqueue(struct work_struct *work) +{ + drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq); + struct drm_device *dev = blitq->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); + unsigned long irqsave; + drm_via_sg_info_t *cur_sg; + int cur_released; + + + DRM_DEBUG("Workqueue task called for blit engine %ld\n", (unsigned long) + (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues)); + + spin_lock_irqsave(&blitq->blit_lock, irqsave); + + while (blitq->serviced != blitq->cur) { + + cur_released = blitq->serviced++; + + DRM_DEBUG("Releasing blit slot %d\n", cur_released); + + if (blitq->serviced >= VIA_NUM_BLIT_SLOTS) + blitq->serviced = 0; + + cur_sg = blitq->blits[cur_released]; + blitq->num_free++; + + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); + + wake_up(&blitq->busy_queue); + + via_free_sg_info(pdev, cur_sg); + kfree(cur_sg); + + spin_lock_irqsave(&blitq->blit_lock, irqsave); + } + + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); +} + +/* + * Init all blit engines. Currently we use two, but some hardware have 4. + */ +static void +via_init_dmablit(struct drm_device *dev) +{ + int i, j; + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; + struct pci_dev *pdev = to_pci_dev(dev->dev); + drm_via_blitq_t *blitq; + + pci_set_master(pdev); + + for (i = 0; i < VIA_NUM_BLIT_ENGINES; ++i) { + blitq = dev_priv->blit_queues + i; + blitq->dev = dev; + blitq->cur_blit_handle = 0; + blitq->done_blit_handle = 0; + blitq->head = 0; + blitq->cur = 0; + blitq->serviced = 0; + blitq->num_free = VIA_NUM_BLIT_SLOTS - 1; + blitq->num_outstanding = 0; + blitq->is_active = 0; + blitq->aborting = 0; + spin_lock_init(&blitq->blit_lock); + for (j = 0; j < VIA_NUM_BLIT_SLOTS; ++j) + init_waitqueue_head(blitq->blit_queue + j); + init_waitqueue_head(&blitq->busy_queue); + INIT_WORK(&blitq->wq, via_dmablit_workqueue); + timer_setup(&blitq->poll_timer, via_dmablit_timer, 0); + } +} + +/* + * Build all info and do all mappings required for a blit. + */ +static int +via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) +{ + struct pci_dev *pdev = to_pci_dev(dev->dev); + int draw = xfer->to_fb; + int ret = 0; + + vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + vsg->bounce_buffer = NULL; + + vsg->state = dr_via_sg_init; + + if (xfer->num_lines <= 0 || xfer->line_length <= 0) { + DRM_ERROR("Zero size bitblt.\n"); + return -EINVAL; + } + + /* + * Below check is a driver limitation, not a hardware one. We + * don't want to lock unused pages, and don't want to incoporate the + * extra logic of avoiding them. Make sure there are no. + * (Not a big limitation anyway.) + */ + + if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) { + DRM_ERROR("Too large system memory stride. Stride: %d, " + "Length: %d\n", xfer->mem_stride, xfer->line_length); + return -EINVAL; + } + + if ((xfer->mem_stride == xfer->line_length) && + (xfer->fb_stride == xfer->line_length)) { + xfer->mem_stride *= xfer->num_lines; + xfer->line_length = xfer->mem_stride; + xfer->fb_stride = xfer->mem_stride; + xfer->num_lines = 1; + } + + /* + * Don't lock an arbitrary large number of pages, since that causes a + * DOS security hole. + */ + + if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) { + DRM_ERROR("Too large PCI DMA bitblt.\n"); + return -EINVAL; + } + + /* + * we allow a negative fb stride to allow flipping of images in + * transfer. + */ + + if (xfer->mem_stride < xfer->line_length || + abs(xfer->fb_stride) < xfer->line_length) { + DRM_ERROR("Invalid frame-buffer / memory stride.\n"); + return -EINVAL; + } + + /* + * A hardware bug seems to be worked around if system memory addresses start on + * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted + * about this. Meanwhile, impose the following restrictions: + */ + +#ifdef VIA_BUGFREE + if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) || + ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) { + DRM_ERROR("Invalid DRM bitblt alignment.\n"); + return -EINVAL; + } +#else + if ((((unsigned long)xfer->mem_addr & 15) || + ((unsigned long)xfer->fb_addr & 3)) || + ((xfer->num_lines > 1) && + ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) { + DRM_ERROR("Invalid DRM bitblt alignment.\n"); + return -EINVAL; + } +#endif + + if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) { + DRM_ERROR("Could not lock DMA pages.\n"); + via_free_sg_info(pdev, vsg); + return ret; + } + + via_map_blit_for_device(pdev, xfer, vsg, 0); + if (0 != (ret = via_alloc_desc_pages(vsg))) { + DRM_ERROR("Could not allocate DMA descriptor pages.\n"); + via_free_sg_info(pdev, vsg); + return ret; + } + via_map_blit_for_device(pdev, xfer, vsg, 1); + + return 0; +} + +/* + * Reserve one free slot in the blit queue. Will wait for one second for one + * to become available. Otherwise -EBUSY is returned. + */ +static int +via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine) +{ + int ret = 0; + unsigned long irqsave; + + DRM_DEBUG("Num free is %d\n", blitq->num_free); + spin_lock_irqsave(&blitq->blit_lock, irqsave); + while (blitq->num_free == 0) { + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); + + VIA_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0); + if (ret) + return (-EINTR == ret) ? -EAGAIN : ret; + + spin_lock_irqsave(&blitq->blit_lock, irqsave); + } + + blitq->num_free--; + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); + + return 0; +} + +/* + * Hand back a free slot if we changed our mind. + */ +static void +via_dmablit_release_slot(drm_via_blitq_t *blitq) +{ + unsigned long irqsave; + + spin_lock_irqsave(&blitq->blit_lock, irqsave); + blitq->num_free++; + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); + wake_up(&blitq->busy_queue); +} + +/* + * Grab a free slot. Build blit info and queue a blit. + */ +static int +via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer) +{ + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; + drm_via_sg_info_t *vsg; + drm_via_blitq_t *blitq; + int ret; + int engine; + unsigned long irqsave; + + if (dev_priv == NULL) { + DRM_ERROR("Called without initialization.\n"); + return -EINVAL; + } + + engine = (xfer->to_fb) ? 0 : 1; + blitq = dev_priv->blit_queues + engine; + if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) + return ret; + if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) { + via_dmablit_release_slot(blitq); + return -ENOMEM; + } + if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) { + via_dmablit_release_slot(blitq); + kfree(vsg); + return ret; + } + spin_lock_irqsave(&blitq->blit_lock, irqsave); + + blitq->blits[blitq->head++] = vsg; + if (blitq->head >= VIA_NUM_BLIT_SLOTS) + blitq->head = 0; + blitq->num_outstanding++; + xfer->sync.sync_handle = ++blitq->cur_blit_handle; + + spin_unlock_irqrestore(&blitq->blit_lock, irqsave); + xfer->sync.engine = engine; + + via_dmablit_handler(dev, engine, 0); + + return 0; +} + +/* + * Sync on a previously submitted blit. Note that the X server use signals extensively, and + * that there is a very big probability that this IOCTL will be interrupted by a signal. In that + * case it returns with -EAGAIN for the signal to be delivered. + * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock(). + */ +static int +via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_blitsync_t *sync = data; + int err; + + if (sync->engine >= VIA_NUM_BLIT_ENGINES) + return -EINVAL; + + err = via_dmablit_sync(dev, sync->sync_handle, sync->engine); + + if (-EINTR == err) + err = -EAGAIN; + + return err; +} + +/* + * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal + * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should + * be reissued. See the above IOCTL code. + */ +static int +via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_via_dmablit_t *xfer = data; + int err; + + err = via_dmablit(dev, xfer); + + return err; +} + static u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe) { drm_via_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index a1bbe3d5247e..6b26decfadb8 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -24,6 +24,7 @@ #ifndef _VIA_DRV_H_ #define _VIA_DRV_H_ +#include <linux/dma-mapping.h> #include <linux/irqreturn.h> #include <linux/jiffies.h> #include <linux/sched.h> @@ -47,12 +48,57 @@ #include "via_verifier.h" -#include "via_dmablit.h" - #define VIA_PCI_BUF_SIZE 60000 #define VIA_FIRE_BUF_SIZE 1024 #define VIA_NUM_IRQS 4 + +#define VIA_NUM_BLIT_ENGINES 2 +#define VIA_NUM_BLIT_SLOTS 8 + +struct _drm_via_descriptor; + +typedef struct _drm_via_sg_info { + struct page **pages; + unsigned long num_pages; + struct _drm_via_descriptor **desc_pages; + int num_desc_pages; + int num_desc; + enum dma_data_direction direction; + unsigned char *bounce_buffer; + dma_addr_t chain_start; + uint32_t free_on_sequence; + unsigned int descriptors_per_page; + int aborted; + enum { + dr_via_device_mapped, + dr_via_desc_pages_alloc, + dr_via_pages_locked, + dr_via_pages_alloc, + dr_via_sg_init + } state; +} drm_via_sg_info_t; + +typedef struct _drm_via_blitq { + struct drm_device *dev; + uint32_t cur_blit_handle; + uint32_t done_blit_handle; + unsigned serviced; + unsigned head; + unsigned cur; + unsigned num_free; + unsigned num_outstanding; + unsigned long end; + int aborting; + int is_active; + drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS]; + spinlock_t blit_lock; + wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS]; + wait_queue_head_t busy_queue; + struct work_struct wq; + struct timer_list poll_timer; +} drm_via_blitq_t; + typedef struct drm_via_ring_buffer { drm_local_map_t map; char *virtual_start; @@ -183,9 +229,6 @@ do { \ remove_wait_queue(&(queue), &entry); \ } while (0) -extern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv); - extern int via_init_context(struct drm_device *dev, int context); extern int via_do_cleanup_map(struct drm_device *dev); @@ -194,7 +237,4 @@ extern int via_dma_cleanup(struct drm_device *dev); extern void via_init_command_verifier(void); extern int via_driver_dma_quiescent(struct drm_device *dev); -extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq); -extern void via_init_dmablit(struct drm_device *dev); - #endif From 8f8ed7f8384f71f841bc70cbdbc2dbeeb7f4bcd5 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:57 +0200 Subject: [PATCH 128/396] drm/via: Embed via_verifier in via_dri1 Embed the header file in via_drv.h and the code in via_dri1. All functions are made static as there are no more external users. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-9-sam@ravnborg.org --- drivers/gpu/drm/via/Makefile | 2 +- drivers/gpu/drm/via/via_dri1.c | 1071 +++++++++++++++++++++++++++ drivers/gpu/drm/via/via_drv.h | 29 +- drivers/gpu/drm/via/via_verifier.c | 1110 ---------------------------- drivers/gpu/drm/via/via_verifier.h | 62 -- 5 files changed, 1099 insertions(+), 1175 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_verifier.c delete mode 100644 drivers/gpu/drm/via/via_verifier.h diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile index 66125b150478..8b978dd51a25 100644 --- a/drivers/gpu/drm/via/Makefile +++ b/drivers/gpu/drm/via/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -via-y := via_dri1.o via_verifier.o +via-y := via_dri1.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index f8b1f837feb1..f9285cc3e1c7 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -201,7 +201,1078 @@ typedef struct _drm_via_descriptor { uint32_t next; } drm_via_descriptor_t; +typedef enum { + state_command, + state_header2, + state_header1, + state_vheader5, + state_vheader6, + state_error +} verifier_state_t; +typedef enum { + no_check = 0, + check_for_header2, + check_for_header1, + check_for_header2_err, + check_for_header1_err, + check_for_fire, + check_z_buffer_addr0, + check_z_buffer_addr1, + check_z_buffer_addr_mode, + check_destination_addr0, + check_destination_addr1, + check_destination_addr_mode, + check_for_dummy, + check_for_dd, + check_texture_addr0, + check_texture_addr1, + check_texture_addr2, + check_texture_addr3, + check_texture_addr4, + check_texture_addr5, + check_texture_addr6, + check_texture_addr7, + check_texture_addr8, + check_texture_addr_mode, + check_for_vertex_count, + check_number_texunits, + forbidden_command +} hazard_t; + +/* + * Associates each hazard above with a possible multi-command + * sequence. For example an address that is split over multiple + * commands and that needs to be checked at the first command + * that does not include any part of the address. + */ + +static drm_via_sequence_t seqs[] = { + no_sequence, + no_sequence, + no_sequence, + no_sequence, + no_sequence, + no_sequence, + z_address, + z_address, + z_address, + dest_address, + dest_address, + dest_address, + no_sequence, + no_sequence, + tex_address, + tex_address, + tex_address, + tex_address, + tex_address, + tex_address, + tex_address, + tex_address, + tex_address, + tex_address, + no_sequence +}; + +typedef struct { + unsigned int code; + hazard_t hz; +} hz_init_t; + +static hz_init_t init_table1[] = { + {0xf2, check_for_header2_err}, + {0xf0, check_for_header1_err}, + {0xee, check_for_fire}, + {0xcc, check_for_dummy}, + {0xdd, check_for_dd}, + {0x00, no_check}, + {0x10, check_z_buffer_addr0}, + {0x11, check_z_buffer_addr1}, + {0x12, check_z_buffer_addr_mode}, + {0x13, no_check}, + {0x14, no_check}, + {0x15, no_check}, + {0x23, no_check}, + {0x24, no_check}, + {0x33, no_check}, + {0x34, no_check}, + {0x35, no_check}, + {0x36, no_check}, + {0x37, no_check}, + {0x38, no_check}, + {0x39, no_check}, + {0x3A, no_check}, + {0x3B, no_check}, + {0x3C, no_check}, + {0x3D, no_check}, + {0x3E, no_check}, + {0x40, check_destination_addr0}, + {0x41, check_destination_addr1}, + {0x42, check_destination_addr_mode}, + {0x43, no_check}, + {0x44, no_check}, + {0x50, no_check}, + {0x51, no_check}, + {0x52, no_check}, + {0x53, no_check}, + {0x54, no_check}, + {0x55, no_check}, + {0x56, no_check}, + {0x57, no_check}, + {0x58, no_check}, + {0x70, no_check}, + {0x71, no_check}, + {0x78, no_check}, + {0x79, no_check}, + {0x7A, no_check}, + {0x7B, no_check}, + {0x7C, no_check}, + {0x7D, check_for_vertex_count} +}; + +static hz_init_t init_table2[] = { + {0xf2, check_for_header2_err}, + {0xf0, check_for_header1_err}, + {0xee, check_for_fire}, + {0xcc, check_for_dummy}, + {0x00, check_texture_addr0}, + {0x01, check_texture_addr0}, + {0x02, check_texture_addr0}, + {0x03, check_texture_addr0}, + {0x04, check_texture_addr0}, + {0x05, check_texture_addr0}, + {0x06, check_texture_addr0}, + {0x07, check_texture_addr0}, + {0x08, check_texture_addr0}, + {0x09, check_texture_addr0}, + {0x20, check_texture_addr1}, + {0x21, check_texture_addr1}, + {0x22, check_texture_addr1}, + {0x23, check_texture_addr4}, + {0x2B, check_texture_addr3}, + {0x2C, check_texture_addr3}, + {0x2D, check_texture_addr3}, + {0x2E, check_texture_addr3}, + {0x2F, check_texture_addr3}, + {0x30, check_texture_addr3}, + {0x31, check_texture_addr3}, + {0x32, check_texture_addr3}, + {0x33, check_texture_addr3}, + {0x34, check_texture_addr3}, + {0x4B, check_texture_addr5}, + {0x4C, check_texture_addr6}, + {0x51, check_texture_addr7}, + {0x52, check_texture_addr8}, + {0x77, check_texture_addr2}, + {0x78, no_check}, + {0x79, no_check}, + {0x7A, no_check}, + {0x7B, check_texture_addr_mode}, + {0x7C, no_check}, + {0x7D, no_check}, + {0x7E, no_check}, + {0x7F, no_check}, + {0x80, no_check}, + {0x81, no_check}, + {0x82, no_check}, + {0x83, no_check}, + {0x85, no_check}, + {0x86, no_check}, + {0x87, no_check}, + {0x88, no_check}, + {0x89, no_check}, + {0x8A, no_check}, + {0x90, no_check}, + {0x91, no_check}, + {0x92, no_check}, + {0x93, no_check} +}; + +static hz_init_t init_table3[] = { + {0xf2, check_for_header2_err}, + {0xf0, check_for_header1_err}, + {0xcc, check_for_dummy}, + {0x00, check_number_texunits} +}; + +static hazard_t table1[256]; +static hazard_t table2[256]; +static hazard_t table3[256]; + +static __inline__ int +eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words) +{ + if ((buf_end - *buf) >= num_words) { + *buf += num_words; + return 0; + } + DRM_ERROR("Illegal termination of DMA command buffer\n"); + return 1; +} + +/* + * Partially stolen from drm_memory.h + */ + +static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq, + unsigned long offset, + unsigned long size, + struct drm_device *dev) +{ + struct drm_map_list *r_list; + drm_local_map_t *map = seq->map_cache; + + if (map && map->offset <= offset + && (offset + size) <= (map->offset + map->size)) { + return map; + } + + list_for_each_entry(r_list, &dev->maplist, head) { + map = r_list->map; + if (!map) + continue; + if (map->offset <= offset + && (offset + size) <= (map->offset + map->size) + && !(map->flags & _DRM_RESTRICTED) + && (map->type == _DRM_AGP)) { + seq->map_cache = map; + return map; + } + } + return NULL; +} + +/* + * Require that all AGP texture levels reside in the same AGP map which should + * be mappable by the client. This is not a big restriction. + * FIXME: To actually enforce this security policy strictly, drm_rmmap + * would have to wait for dma quiescent before removing an AGP map. + * The via_drm_lookup_agp_map call in reality seems to take + * very little CPU time. + */ + +static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) +{ + switch (cur_seq->unfinished) { + case z_address: + DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr); + break; + case dest_address: + DRM_DEBUG("Destination start address is 0x%x\n", + cur_seq->d_addr); + break; + case tex_address: + if (cur_seq->agp_texture) { + unsigned start = + cur_seq->tex_level_lo[cur_seq->texture]; + unsigned end = cur_seq->tex_level_hi[cur_seq->texture]; + unsigned long lo = ~0, hi = 0, tmp; + uint32_t *addr, *pitch, *height, tex; + unsigned i; + int npot; + + if (end > 9) + end = 9; + if (start > 9) + start = 9; + + addr = + &(cur_seq->t_addr[tex = cur_seq->texture][start]); + pitch = &(cur_seq->pitch[tex][start]); + height = &(cur_seq->height[tex][start]); + npot = cur_seq->tex_npot[tex]; + for (i = start; i <= end; ++i) { + tmp = *addr++; + if (tmp < lo) + lo = tmp; + if (i == 0 && npot) + tmp += (*height++ * *pitch++); + else + tmp += (*height++ << *pitch++); + if (tmp > hi) + hi = tmp; + } + + if (!via_drm_lookup_agp_map + (cur_seq, lo, hi - lo, cur_seq->dev)) { + DRM_ERROR + ("AGP texture is not in allowed map\n"); + return 2; + } + } + break; + default: + break; + } + cur_seq->unfinished = no_sequence; + return 0; +} + +static __inline__ int +investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq) +{ + register uint32_t tmp, *tmp_addr; + + if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) { + int ret; + if ((ret = finish_current_sequence(cur_seq))) + return ret; + } + + switch (hz) { + case check_for_header2: + if (cmd == HALCYON_HEADER2) + return 1; + return 0; + case check_for_header1: + if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) + return 1; + return 0; + case check_for_header2_err: + if (cmd == HALCYON_HEADER2) + return 1; + DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n"); + break; + case check_for_header1_err: + if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) + return 1; + DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n"); + break; + case check_for_fire: + if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD) + return 1; + DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n"); + break; + case check_for_dummy: + if (HC_DUMMY == cmd) + return 0; + DRM_ERROR("Illegal DMA HC_DUMMY command\n"); + break; + case check_for_dd: + if (0xdddddddd == cmd) + return 0; + DRM_ERROR("Illegal DMA 0xdddddddd command\n"); + break; + case check_z_buffer_addr0: + cur_seq->unfinished = z_address; + cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) | + (cmd & 0x00FFFFFF); + return 0; + case check_z_buffer_addr1: + cur_seq->unfinished = z_address; + cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) | + ((cmd & 0xFF) << 24); + return 0; + case check_z_buffer_addr_mode: + cur_seq->unfinished = z_address; + if ((cmd & 0x0000C000) == 0) + return 0; + DRM_ERROR("Attempt to place Z buffer in system memory\n"); + return 2; + case check_destination_addr0: + cur_seq->unfinished = dest_address; + cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) | + (cmd & 0x00FFFFFF); + return 0; + case check_destination_addr1: + cur_seq->unfinished = dest_address; + cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) | + ((cmd & 0xFF) << 24); + return 0; + case check_destination_addr_mode: + cur_seq->unfinished = dest_address; + if ((cmd & 0x0000C000) == 0) + return 0; + DRM_ERROR + ("Attempt to place 3D drawing buffer in system memory\n"); + return 2; + case check_texture_addr0: + cur_seq->unfinished = tex_address; + tmp = (cmd >> 24); + tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp]; + *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF); + return 0; + case check_texture_addr1: + cur_seq->unfinished = tex_address; + tmp = ((cmd >> 24) - 0x20); + tmp += tmp << 1; + tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp]; + *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24); + tmp_addr++; + *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16); + tmp_addr++; + *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8); + return 0; + case check_texture_addr2: + cur_seq->unfinished = tex_address; + cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F; + cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6; + return 0; + case check_texture_addr3: + cur_seq->unfinished = tex_address; + tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit); + if (tmp == 0 && + (cmd & HC_HTXnEnPit_MASK)) { + cur_seq->pitch[cur_seq->texture][tmp] = + (cmd & HC_HTXnLnPit_MASK); + cur_seq->tex_npot[cur_seq->texture] = 1; + } else { + cur_seq->pitch[cur_seq->texture][tmp] = + (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT; + cur_seq->tex_npot[cur_seq->texture] = 0; + if (cmd & 0x000FFFFF) { + DRM_ERROR + ("Unimplemented texture level 0 pitch mode.\n"); + return 2; + } + } + return 0; + case check_texture_addr4: + cur_seq->unfinished = tex_address; + tmp_addr = &cur_seq->t_addr[cur_seq->texture][9]; + *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24); + return 0; + case check_texture_addr5: + case check_texture_addr6: + cur_seq->unfinished = tex_address; + /* + * Texture width. We don't care since we have the pitch. + */ + return 0; + case check_texture_addr7: + cur_seq->unfinished = tex_address; + tmp_addr = &(cur_seq->height[cur_seq->texture][0]); + tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20); + tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16); + tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12); + tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8); + tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4); + tmp_addr[0] = 1 << (cmd & 0x0000000F); + return 0; + case check_texture_addr8: + cur_seq->unfinished = tex_address; + tmp_addr = &(cur_seq->height[cur_seq->texture][0]); + tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12); + tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8); + tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4); + tmp_addr[6] = 1 << (cmd & 0x0000000F); + return 0; + case check_texture_addr_mode: + cur_seq->unfinished = tex_address; + if (2 == (tmp = cmd & 0x00000003)) { + DRM_ERROR + ("Attempt to fetch texture from system memory.\n"); + return 2; + } + cur_seq->agp_texture = (tmp == 3); + cur_seq->tex_palette_size[cur_seq->texture] = + (cmd >> 16) & 0x000000007; + return 0; + case check_for_vertex_count: + cur_seq->vertex_count = cmd & 0x0000FFFF; + return 0; + case check_number_texunits: + cur_seq->multitex = (cmd >> 3) & 1; + return 0; + default: + DRM_ERROR("Illegal DMA data: 0x%x\n", cmd); + return 2; + } + return 2; +} + +static __inline__ int +via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end, + drm_via_state_t *cur_seq) +{ + drm_via_private_t *dev_priv = + (drm_via_private_t *) cur_seq->dev->dev_private; + uint32_t a_fire, bcmd, dw_count; + int ret = 0; + int have_fire; + const uint32_t *buf = *buffer; + + while (buf < buf_end) { + have_fire = 0; + if ((buf_end - buf) < 2) { + DRM_ERROR + ("Unexpected termination of primitive list.\n"); + ret = 1; + break; + } + if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB) + break; + bcmd = *buf++; + if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) { + DRM_ERROR("Expected Vertex List A command, got 0x%x\n", + *buf); + ret = 1; + break; + } + a_fire = + *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK | + HC_HE3Fire_MASK; + + /* + * How many dwords per vertex ? + */ + + if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) { + DRM_ERROR("Illegal B command vertex data for AGP.\n"); + ret = 1; + break; + } + + dw_count = 0; + if (bcmd & (1 << 7)) + dw_count += (cur_seq->multitex) ? 2 : 1; + if (bcmd & (1 << 8)) + dw_count += (cur_seq->multitex) ? 2 : 1; + if (bcmd & (1 << 9)) + dw_count++; + if (bcmd & (1 << 10)) + dw_count++; + if (bcmd & (1 << 11)) + dw_count++; + if (bcmd & (1 << 12)) + dw_count++; + if (bcmd & (1 << 13)) + dw_count++; + if (bcmd & (1 << 14)) + dw_count++; + + while (buf < buf_end) { + if (*buf == a_fire) { + if (dev_priv->num_fire_offsets >= + VIA_FIRE_BUF_SIZE) { + DRM_ERROR("Fire offset buffer full.\n"); + ret = 1; + break; + } + dev_priv->fire_offsets[dev_priv-> + num_fire_offsets++] = + buf; + have_fire = 1; + buf++; + if (buf < buf_end && *buf == a_fire) + buf++; + break; + } + if ((*buf == HALCYON_HEADER2) || + ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) { + DRM_ERROR("Missing Vertex Fire command, " + "Stray Vertex Fire command or verifier " + "lost sync.\n"); + ret = 1; + break; + } + if ((ret = eat_words(&buf, buf_end, dw_count))) + break; + } + if (buf >= buf_end && !have_fire) { + DRM_ERROR("Missing Vertex Fire command or verifier " + "lost sync.\n"); + ret = 1; + break; + } + if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) { + DRM_ERROR("AGP Primitive list end misaligned.\n"); + ret = 1; + break; + } + } + *buffer = buf; + return ret; +} + +static __inline__ verifier_state_t +via_check_header2(uint32_t const **buffer, const uint32_t *buf_end, + drm_via_state_t *hc_state) +{ + uint32_t cmd; + int hz_mode; + hazard_t hz; + const uint32_t *buf = *buffer; + const hazard_t *hz_table; + + if ((buf_end - buf) < 2) { + DRM_ERROR + ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n"); + return state_error; + } + buf++; + cmd = (*buf++ & 0xFFFF0000) >> 16; + + switch (cmd) { + case HC_ParaType_CmdVdata: + if (via_check_prim_list(&buf, buf_end, hc_state)) + return state_error; + *buffer = buf; + return state_command; + case HC_ParaType_NotTex: + hz_table = table1; + break; + case HC_ParaType_Tex: + hc_state->texture = 0; + hz_table = table2; + break; + case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)): + hc_state->texture = 1; + hz_table = table2; + break; + case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)): + hz_table = table3; + break; + case HC_ParaType_Auto: + if (eat_words(&buf, buf_end, 2)) + return state_error; + *buffer = buf; + return state_command; + case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)): + if (eat_words(&buf, buf_end, 32)) + return state_error; + *buffer = buf; + return state_command; + case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)): + case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)): + DRM_ERROR("Texture palettes are rejected because of " + "lack of info how to determine their size.\n"); + return state_error; + case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)): + DRM_ERROR("Fog factor palettes are rejected because of " + "lack of info how to determine their size.\n"); + return state_error; + default: + + /* + * There are some unimplemented HC_ParaTypes here, that + * need to be implemented if the Mesa driver is extended. + */ + + DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 " + "DMA subcommand: 0x%x. Previous dword: 0x%x\n", + cmd, *(buf - 2)); + *buffer = buf; + return state_error; + } + + while (buf < buf_end) { + cmd = *buf++; + if ((hz = hz_table[cmd >> 24])) { + if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) { + if (hz_mode == 1) { + buf--; + break; + } + return state_error; + } + } else if (hc_state->unfinished && + finish_current_sequence(hc_state)) { + return state_error; + } + } + if (hc_state->unfinished && finish_current_sequence(hc_state)) + return state_error; + *buffer = buf; + return state_command; +} + +static __inline__ verifier_state_t +via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer, + const uint32_t *buf_end, int *fire_count) +{ + uint32_t cmd; + const uint32_t *buf = *buffer; + const uint32_t *next_fire; + int burst = 0; + + next_fire = dev_priv->fire_offsets[*fire_count]; + buf++; + cmd = (*buf & 0xFFFF0000) >> 16; + via_write(dev_priv, HC_REG_TRANS_SET + HC_REG_BASE, *buf++); + switch (cmd) { + case HC_ParaType_CmdVdata: + while ((buf < buf_end) && + (*fire_count < dev_priv->num_fire_offsets) && + (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) { + while (buf <= next_fire) { + via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE + + (burst & 63), *buf++); + burst += 4; + } + if ((buf < buf_end) + && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) + buf++; + + if (++(*fire_count) < dev_priv->num_fire_offsets) + next_fire = dev_priv->fire_offsets[*fire_count]; + } + break; + default: + while (buf < buf_end) { + + if (*buf == HC_HEADER2 || + (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 || + (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 || + (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) + break; + + via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE + + (burst & 63), *buf++); + burst += 4; + } + } + *buffer = buf; + return state_command; +} + +static __inline__ int verify_mmio_address(uint32_t address) +{ + if ((address > 0x3FF) && (address < 0xC00)) { + DRM_ERROR("Invalid VIDEO DMA command. " + "Attempt to access 3D- or command burst area.\n"); + return 1; + } else if ((address > 0xCFF) && (address < 0x1300)) { + DRM_ERROR("Invalid VIDEO DMA command. " + "Attempt to access PCI DMA area.\n"); + return 1; + } else if (address > 0x13FF) { + DRM_ERROR("Invalid VIDEO DMA command. " + "Attempt to access VGA registers.\n"); + return 1; + } + return 0; +} + +static __inline__ int +verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end, + uint32_t dwords) +{ + const uint32_t *buf = *buffer; + + if (buf_end - buf < dwords) { + DRM_ERROR("Illegal termination of video command.\n"); + return 1; + } + while (dwords--) { + if (*buf++) { + DRM_ERROR("Illegal video command tail.\n"); + return 1; + } + } + *buffer = buf; + return 0; +} + +static __inline__ verifier_state_t +via_check_header1(uint32_t const **buffer, const uint32_t * buf_end) +{ + uint32_t cmd; + const uint32_t *buf = *buffer; + verifier_state_t ret = state_command; + + while (buf < buf_end) { + cmd = *buf; + if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) && + (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) { + if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) + break; + DRM_ERROR("Invalid HALCYON_HEADER1 command. " + "Attempt to access 3D- or command burst area.\n"); + ret = state_error; + break; + } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) { + if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) + break; + DRM_ERROR("Invalid HALCYON_HEADER1 command. " + "Attempt to access VGA registers.\n"); + ret = state_error; + break; + } else { + buf += 2; + } + } + *buffer = buf; + return ret; +} + +static __inline__ verifier_state_t +via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer, + const uint32_t *buf_end) +{ + register uint32_t cmd; + const uint32_t *buf = *buffer; + + while (buf < buf_end) { + cmd = *buf; + if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) + break; + via_write(dev_priv, (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf); + buf++; + } + *buffer = buf; + return state_command; +} + +static __inline__ verifier_state_t +via_check_vheader5(uint32_t const **buffer, const uint32_t *buf_end) +{ + uint32_t data; + const uint32_t *buf = *buffer; + + if (buf_end - buf < 4) { + DRM_ERROR("Illegal termination of video header5 command\n"); + return state_error; + } + + data = *buf++ & ~VIA_VIDEOMASK; + if (verify_mmio_address(data)) + return state_error; + + data = *buf++; + if (*buf++ != 0x00F50000) { + DRM_ERROR("Illegal header5 header data\n"); + return state_error; + } + if (*buf++ != 0x00000000) { + DRM_ERROR("Illegal header5 header data\n"); + return state_error; + } + if (eat_words(&buf, buf_end, data)) + return state_error; + if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3))) + return state_error; + *buffer = buf; + return state_command; + +} + +static __inline__ verifier_state_t +via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer, + const uint32_t *buf_end) +{ + uint32_t addr, count, i; + const uint32_t *buf = *buffer; + + addr = *buf++ & ~VIA_VIDEOMASK; + i = count = *buf; + buf += 3; + while (i--) + via_write(dev_priv, addr, *buf++); + if (count & 3) + buf += 4 - (count & 3); + *buffer = buf; + return state_command; +} + +static __inline__ verifier_state_t +via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end) +{ + uint32_t data; + const uint32_t *buf = *buffer; + uint32_t i; + + if (buf_end - buf < 4) { + DRM_ERROR("Illegal termination of video header6 command\n"); + return state_error; + } + buf++; + data = *buf++; + if (*buf++ != 0x00F60000) { + DRM_ERROR("Illegal header6 header data\n"); + return state_error; + } + if (*buf++ != 0x00000000) { + DRM_ERROR("Illegal header6 header data\n"); + return state_error; + } + if ((buf_end - buf) < (data << 1)) { + DRM_ERROR("Illegal termination of video header6 command\n"); + return state_error; + } + for (i = 0; i < data; ++i) { + if (verify_mmio_address(*buf++)) + return state_error; + buf++; + } + data <<= 1; + if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3))) + return state_error; + *buffer = buf; + return state_command; +} + +static __inline__ verifier_state_t +via_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer, + const uint32_t *buf_end) +{ + + uint32_t addr, count, i; + const uint32_t *buf = *buffer; + + i = count = *++buf; + buf += 3; + while (i--) { + addr = *buf++; + via_write(dev_priv, addr, *buf++); + } + count <<= 1; + if (count & 3) + buf += 4 - (count & 3); + *buffer = buf; + return state_command; +} + +static int +via_verify_command_stream(const uint32_t * buf, unsigned int size, + struct drm_device * dev, int agp) +{ + + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + drm_via_state_t *hc_state = &dev_priv->hc_state; + drm_via_state_t saved_state = *hc_state; + uint32_t cmd; + const uint32_t *buf_end = buf + (size >> 2); + verifier_state_t state = state_command; + int cme_video; + int supported_3d; + + cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A || + dev_priv->chipset == VIA_DX9_0); + + supported_3d = dev_priv->chipset != VIA_DX9_0; + + hc_state->dev = dev; + hc_state->unfinished = no_sequence; + hc_state->map_cache = NULL; + hc_state->agp = agp; + hc_state->buf_start = buf; + dev_priv->num_fire_offsets = 0; + + while (buf < buf_end) { + + switch (state) { + case state_header2: + state = via_check_header2(&buf, buf_end, hc_state); + break; + case state_header1: + state = via_check_header1(&buf, buf_end); + break; + case state_vheader5: + state = via_check_vheader5(&buf, buf_end); + break; + case state_vheader6: + state = via_check_vheader6(&buf, buf_end); + break; + case state_command: + cmd = *buf; + if ((cmd == HALCYON_HEADER2) && supported_3d) + state = state_header2; + else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) + state = state_header1; + else if (cme_video + && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) + state = state_vheader5; + else if (cme_video + && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) + state = state_vheader6; + else if ((cmd == HALCYON_HEADER2) && !supported_3d) { + DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n"); + state = state_error; + } else { + DRM_ERROR + ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", + cmd); + state = state_error; + } + break; + case state_error: + default: + *hc_state = saved_state; + return -EINVAL; + } + } + if (state == state_error) { + *hc_state = saved_state; + return -EINVAL; + } + return 0; +} + +static int +via_parse_command_stream(struct drm_device *dev, const uint32_t *buf, + unsigned int size) +{ + + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + uint32_t cmd; + const uint32_t *buf_end = buf + (size >> 2); + verifier_state_t state = state_command; + int fire_count = 0; + + while (buf < buf_end) { + + switch (state) { + case state_header2: + state = + via_parse_header2(dev_priv, &buf, buf_end, + &fire_count); + break; + case state_header1: + state = via_parse_header1(dev_priv, &buf, buf_end); + break; + case state_vheader5: + state = via_parse_vheader5(dev_priv, &buf, buf_end); + break; + case state_vheader6: + state = via_parse_vheader6(dev_priv, &buf, buf_end); + break; + case state_command: + cmd = *buf; + if (cmd == HALCYON_HEADER2) + state = state_header2; + else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) + state = state_header1; + else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) + state = state_vheader5; + else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) + state = state_vheader6; + else { + DRM_ERROR + ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", + cmd); + state = state_error; + } + break; + case state_error: + default: + return -EINVAL; + } + } + if (state == state_error) + return -EINVAL; + return 0; +} + +static void +setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size) +{ + int i; + + for (i = 0; i < 256; ++i) + table[i] = forbidden_command; + + for (i = 0; i < size; ++i) + table[init_table[i].code] = init_table[i].hz; +} + +static void via_init_command_verifier(void) +{ + setup_hazard_table(init_table1, table1, ARRAY_SIZE(init_table1)); + setup_hazard_table(init_table2, table2, ARRAY_SIZE(init_table2)); + setup_hazard_table(init_table3, table3, ARRAY_SIZE(init_table3)); +} /* * Unmap a DMA mapping. */ diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 6b26decfadb8..640a7701f606 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -46,7 +46,33 @@ #define DRIVER_MINOR 11 #define DRIVER_PATCHLEVEL 1 -#include "via_verifier.h" +typedef enum { + no_sequence = 0, + z_address, + dest_address, + tex_address +} drm_via_sequence_t; + +typedef struct { + unsigned texture; + uint32_t z_addr; + uint32_t d_addr; + uint32_t t_addr[2][10]; + uint32_t pitch[2][10]; + uint32_t height[2][10]; + uint32_t tex_level_lo[2]; + uint32_t tex_level_hi[2]; + uint32_t tex_palette_size[2]; + uint32_t tex_npot[2]; + drm_via_sequence_t unfinished; + int agp_texture; + int multitex; + struct drm_device *dev; + drm_local_map_t *map_cache; + uint32_t vertex_count; + int agp; + const uint32_t *buf_start; +} drm_via_state_t; #define VIA_PCI_BUF_SIZE 60000 #define VIA_FIRE_BUF_SIZE 1024 @@ -234,7 +260,6 @@ extern int via_init_context(struct drm_device *dev, int context); extern int via_do_cleanup_map(struct drm_device *dev); extern int via_dma_cleanup(struct drm_device *dev); -extern void via_init_command_verifier(void); extern int via_driver_dma_quiescent(struct drm_device *dev); #endif diff --git a/drivers/gpu/drm/via/via_verifier.c b/drivers/gpu/drm/via/via_verifier.c deleted file mode 100644 index 3d6e3a70f318..000000000000 --- a/drivers/gpu/drm/via/via_verifier.c +++ /dev/null @@ -1,1110 +0,0 @@ -/* - * Copyright 2004 The Unichrome Project. All Rights Reserved. - * Copyright 2005 Thomas Hellstrom. All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) 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. - * - * Author: Thomas Hellstrom 2004, 2005. - * This code was written using docs obtained under NDA from VIA Inc. - * - * Don't run this code directly on an AGP buffer. Due to cache problems it will - * be very slow. - */ - -#include <drm/drm_device.h> -#include <drm/drm_legacy.h> -#include <drm/via_drm.h> - -#include "via_3d_reg.h" -#include "via_drv.h" -#include "via_verifier.h" - -typedef enum { - state_command, - state_header2, - state_header1, - state_vheader5, - state_vheader6, - state_error -} verifier_state_t; - -typedef enum { - no_check = 0, - check_for_header2, - check_for_header1, - check_for_header2_err, - check_for_header1_err, - check_for_fire, - check_z_buffer_addr0, - check_z_buffer_addr1, - check_z_buffer_addr_mode, - check_destination_addr0, - check_destination_addr1, - check_destination_addr_mode, - check_for_dummy, - check_for_dd, - check_texture_addr0, - check_texture_addr1, - check_texture_addr2, - check_texture_addr3, - check_texture_addr4, - check_texture_addr5, - check_texture_addr6, - check_texture_addr7, - check_texture_addr8, - check_texture_addr_mode, - check_for_vertex_count, - check_number_texunits, - forbidden_command -} hazard_t; - -/* - * Associates each hazard above with a possible multi-command - * sequence. For example an address that is split over multiple - * commands and that needs to be checked at the first command - * that does not include any part of the address. - */ - -static drm_via_sequence_t seqs[] = { - no_sequence, - no_sequence, - no_sequence, - no_sequence, - no_sequence, - no_sequence, - z_address, - z_address, - z_address, - dest_address, - dest_address, - dest_address, - no_sequence, - no_sequence, - tex_address, - tex_address, - tex_address, - tex_address, - tex_address, - tex_address, - tex_address, - tex_address, - tex_address, - tex_address, - no_sequence -}; - -typedef struct { - unsigned int code; - hazard_t hz; -} hz_init_t; - -static hz_init_t init_table1[] = { - {0xf2, check_for_header2_err}, - {0xf0, check_for_header1_err}, - {0xee, check_for_fire}, - {0xcc, check_for_dummy}, - {0xdd, check_for_dd}, - {0x00, no_check}, - {0x10, check_z_buffer_addr0}, - {0x11, check_z_buffer_addr1}, - {0x12, check_z_buffer_addr_mode}, - {0x13, no_check}, - {0x14, no_check}, - {0x15, no_check}, - {0x23, no_check}, - {0x24, no_check}, - {0x33, no_check}, - {0x34, no_check}, - {0x35, no_check}, - {0x36, no_check}, - {0x37, no_check}, - {0x38, no_check}, - {0x39, no_check}, - {0x3A, no_check}, - {0x3B, no_check}, - {0x3C, no_check}, - {0x3D, no_check}, - {0x3E, no_check}, - {0x40, check_destination_addr0}, - {0x41, check_destination_addr1}, - {0x42, check_destination_addr_mode}, - {0x43, no_check}, - {0x44, no_check}, - {0x50, no_check}, - {0x51, no_check}, - {0x52, no_check}, - {0x53, no_check}, - {0x54, no_check}, - {0x55, no_check}, - {0x56, no_check}, - {0x57, no_check}, - {0x58, no_check}, - {0x70, no_check}, - {0x71, no_check}, - {0x78, no_check}, - {0x79, no_check}, - {0x7A, no_check}, - {0x7B, no_check}, - {0x7C, no_check}, - {0x7D, check_for_vertex_count} -}; - -static hz_init_t init_table2[] = { - {0xf2, check_for_header2_err}, - {0xf0, check_for_header1_err}, - {0xee, check_for_fire}, - {0xcc, check_for_dummy}, - {0x00, check_texture_addr0}, - {0x01, check_texture_addr0}, - {0x02, check_texture_addr0}, - {0x03, check_texture_addr0}, - {0x04, check_texture_addr0}, - {0x05, check_texture_addr0}, - {0x06, check_texture_addr0}, - {0x07, check_texture_addr0}, - {0x08, check_texture_addr0}, - {0x09, check_texture_addr0}, - {0x20, check_texture_addr1}, - {0x21, check_texture_addr1}, - {0x22, check_texture_addr1}, - {0x23, check_texture_addr4}, - {0x2B, check_texture_addr3}, - {0x2C, check_texture_addr3}, - {0x2D, check_texture_addr3}, - {0x2E, check_texture_addr3}, - {0x2F, check_texture_addr3}, - {0x30, check_texture_addr3}, - {0x31, check_texture_addr3}, - {0x32, check_texture_addr3}, - {0x33, check_texture_addr3}, - {0x34, check_texture_addr3}, - {0x4B, check_texture_addr5}, - {0x4C, check_texture_addr6}, - {0x51, check_texture_addr7}, - {0x52, check_texture_addr8}, - {0x77, check_texture_addr2}, - {0x78, no_check}, - {0x79, no_check}, - {0x7A, no_check}, - {0x7B, check_texture_addr_mode}, - {0x7C, no_check}, - {0x7D, no_check}, - {0x7E, no_check}, - {0x7F, no_check}, - {0x80, no_check}, - {0x81, no_check}, - {0x82, no_check}, - {0x83, no_check}, - {0x85, no_check}, - {0x86, no_check}, - {0x87, no_check}, - {0x88, no_check}, - {0x89, no_check}, - {0x8A, no_check}, - {0x90, no_check}, - {0x91, no_check}, - {0x92, no_check}, - {0x93, no_check} -}; - -static hz_init_t init_table3[] = { - {0xf2, check_for_header2_err}, - {0xf0, check_for_header1_err}, - {0xcc, check_for_dummy}, - {0x00, check_number_texunits} -}; - -static hazard_t table1[256]; -static hazard_t table2[256]; -static hazard_t table3[256]; - -static __inline__ int -eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words) -{ - if ((buf_end - *buf) >= num_words) { - *buf += num_words; - return 0; - } - DRM_ERROR("Illegal termination of DMA command buffer\n"); - return 1; -} - -/* - * Partially stolen from drm_memory.h - */ - -static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq, - unsigned long offset, - unsigned long size, - struct drm_device *dev) -{ - struct drm_map_list *r_list; - drm_local_map_t *map = seq->map_cache; - - if (map && map->offset <= offset - && (offset + size) <= (map->offset + map->size)) { - return map; - } - - list_for_each_entry(r_list, &dev->maplist, head) { - map = r_list->map; - if (!map) - continue; - if (map->offset <= offset - && (offset + size) <= (map->offset + map->size) - && !(map->flags & _DRM_RESTRICTED) - && (map->type == _DRM_AGP)) { - seq->map_cache = map; - return map; - } - } - return NULL; -} - -/* - * Require that all AGP texture levels reside in the same AGP map which should - * be mappable by the client. This is not a big restriction. - * FIXME: To actually enforce this security policy strictly, drm_rmmap - * would have to wait for dma quiescent before removing an AGP map. - * The via_drm_lookup_agp_map call in reality seems to take - * very little CPU time. - */ - -static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) -{ - switch (cur_seq->unfinished) { - case z_address: - DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr); - break; - case dest_address: - DRM_DEBUG("Destination start address is 0x%x\n", - cur_seq->d_addr); - break; - case tex_address: - if (cur_seq->agp_texture) { - unsigned start = - cur_seq->tex_level_lo[cur_seq->texture]; - unsigned end = cur_seq->tex_level_hi[cur_seq->texture]; - unsigned long lo = ~0, hi = 0, tmp; - uint32_t *addr, *pitch, *height, tex; - unsigned i; - int npot; - - if (end > 9) - end = 9; - if (start > 9) - start = 9; - - addr = - &(cur_seq->t_addr[tex = cur_seq->texture][start]); - pitch = &(cur_seq->pitch[tex][start]); - height = &(cur_seq->height[tex][start]); - npot = cur_seq->tex_npot[tex]; - for (i = start; i <= end; ++i) { - tmp = *addr++; - if (tmp < lo) - lo = tmp; - if (i == 0 && npot) - tmp += (*height++ * *pitch++); - else - tmp += (*height++ << *pitch++); - if (tmp > hi) - hi = tmp; - } - - if (!via_drm_lookup_agp_map - (cur_seq, lo, hi - lo, cur_seq->dev)) { - DRM_ERROR - ("AGP texture is not in allowed map\n"); - return 2; - } - } - break; - default: - break; - } - cur_seq->unfinished = no_sequence; - return 0; -} - -static __inline__ int -investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq) -{ - register uint32_t tmp, *tmp_addr; - - if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) { - int ret; - if ((ret = finish_current_sequence(cur_seq))) - return ret; - } - - switch (hz) { - case check_for_header2: - if (cmd == HALCYON_HEADER2) - return 1; - return 0; - case check_for_header1: - if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) - return 1; - return 0; - case check_for_header2_err: - if (cmd == HALCYON_HEADER2) - return 1; - DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n"); - break; - case check_for_header1_err: - if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) - return 1; - DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n"); - break; - case check_for_fire: - if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD) - return 1; - DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n"); - break; - case check_for_dummy: - if (HC_DUMMY == cmd) - return 0; - DRM_ERROR("Illegal DMA HC_DUMMY command\n"); - break; - case check_for_dd: - if (0xdddddddd == cmd) - return 0; - DRM_ERROR("Illegal DMA 0xdddddddd command\n"); - break; - case check_z_buffer_addr0: - cur_seq->unfinished = z_address; - cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) | - (cmd & 0x00FFFFFF); - return 0; - case check_z_buffer_addr1: - cur_seq->unfinished = z_address; - cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) | - ((cmd & 0xFF) << 24); - return 0; - case check_z_buffer_addr_mode: - cur_seq->unfinished = z_address; - if ((cmd & 0x0000C000) == 0) - return 0; - DRM_ERROR("Attempt to place Z buffer in system memory\n"); - return 2; - case check_destination_addr0: - cur_seq->unfinished = dest_address; - cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) | - (cmd & 0x00FFFFFF); - return 0; - case check_destination_addr1: - cur_seq->unfinished = dest_address; - cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) | - ((cmd & 0xFF) << 24); - return 0; - case check_destination_addr_mode: - cur_seq->unfinished = dest_address; - if ((cmd & 0x0000C000) == 0) - return 0; - DRM_ERROR - ("Attempt to place 3D drawing buffer in system memory\n"); - return 2; - case check_texture_addr0: - cur_seq->unfinished = tex_address; - tmp = (cmd >> 24); - tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp]; - *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF); - return 0; - case check_texture_addr1: - cur_seq->unfinished = tex_address; - tmp = ((cmd >> 24) - 0x20); - tmp += tmp << 1; - tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp]; - *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24); - tmp_addr++; - *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16); - tmp_addr++; - *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8); - return 0; - case check_texture_addr2: - cur_seq->unfinished = tex_address; - cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F; - cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6; - return 0; - case check_texture_addr3: - cur_seq->unfinished = tex_address; - tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit); - if (tmp == 0 && - (cmd & HC_HTXnEnPit_MASK)) { - cur_seq->pitch[cur_seq->texture][tmp] = - (cmd & HC_HTXnLnPit_MASK); - cur_seq->tex_npot[cur_seq->texture] = 1; - } else { - cur_seq->pitch[cur_seq->texture][tmp] = - (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT; - cur_seq->tex_npot[cur_seq->texture] = 0; - if (cmd & 0x000FFFFF) { - DRM_ERROR - ("Unimplemented texture level 0 pitch mode.\n"); - return 2; - } - } - return 0; - case check_texture_addr4: - cur_seq->unfinished = tex_address; - tmp_addr = &cur_seq->t_addr[cur_seq->texture][9]; - *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24); - return 0; - case check_texture_addr5: - case check_texture_addr6: - cur_seq->unfinished = tex_address; - /* - * Texture width. We don't care since we have the pitch. - */ - return 0; - case check_texture_addr7: - cur_seq->unfinished = tex_address; - tmp_addr = &(cur_seq->height[cur_seq->texture][0]); - tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20); - tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16); - tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12); - tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8); - tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4); - tmp_addr[0] = 1 << (cmd & 0x0000000F); - return 0; - case check_texture_addr8: - cur_seq->unfinished = tex_address; - tmp_addr = &(cur_seq->height[cur_seq->texture][0]); - tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12); - tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8); - tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4); - tmp_addr[6] = 1 << (cmd & 0x0000000F); - return 0; - case check_texture_addr_mode: - cur_seq->unfinished = tex_address; - if (2 == (tmp = cmd & 0x00000003)) { - DRM_ERROR - ("Attempt to fetch texture from system memory.\n"); - return 2; - } - cur_seq->agp_texture = (tmp == 3); - cur_seq->tex_palette_size[cur_seq->texture] = - (cmd >> 16) & 0x000000007; - return 0; - case check_for_vertex_count: - cur_seq->vertex_count = cmd & 0x0000FFFF; - return 0; - case check_number_texunits: - cur_seq->multitex = (cmd >> 3) & 1; - return 0; - default: - DRM_ERROR("Illegal DMA data: 0x%x\n", cmd); - return 2; - } - return 2; -} - -static __inline__ int -via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end, - drm_via_state_t *cur_seq) -{ - drm_via_private_t *dev_priv = - (drm_via_private_t *) cur_seq->dev->dev_private; - uint32_t a_fire, bcmd, dw_count; - int ret = 0; - int have_fire; - const uint32_t *buf = *buffer; - - while (buf < buf_end) { - have_fire = 0; - if ((buf_end - buf) < 2) { - DRM_ERROR - ("Unexpected termination of primitive list.\n"); - ret = 1; - break; - } - if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB) - break; - bcmd = *buf++; - if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) { - DRM_ERROR("Expected Vertex List A command, got 0x%x\n", - *buf); - ret = 1; - break; - } - a_fire = - *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK | - HC_HE3Fire_MASK; - - /* - * How many dwords per vertex ? - */ - - if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) { - DRM_ERROR("Illegal B command vertex data for AGP.\n"); - ret = 1; - break; - } - - dw_count = 0; - if (bcmd & (1 << 7)) - dw_count += (cur_seq->multitex) ? 2 : 1; - if (bcmd & (1 << 8)) - dw_count += (cur_seq->multitex) ? 2 : 1; - if (bcmd & (1 << 9)) - dw_count++; - if (bcmd & (1 << 10)) - dw_count++; - if (bcmd & (1 << 11)) - dw_count++; - if (bcmd & (1 << 12)) - dw_count++; - if (bcmd & (1 << 13)) - dw_count++; - if (bcmd & (1 << 14)) - dw_count++; - - while (buf < buf_end) { - if (*buf == a_fire) { - if (dev_priv->num_fire_offsets >= - VIA_FIRE_BUF_SIZE) { - DRM_ERROR("Fire offset buffer full.\n"); - ret = 1; - break; - } - dev_priv->fire_offsets[dev_priv-> - num_fire_offsets++] = - buf; - have_fire = 1; - buf++; - if (buf < buf_end && *buf == a_fire) - buf++; - break; - } - if ((*buf == HALCYON_HEADER2) || - ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) { - DRM_ERROR("Missing Vertex Fire command, " - "Stray Vertex Fire command or verifier " - "lost sync.\n"); - ret = 1; - break; - } - if ((ret = eat_words(&buf, buf_end, dw_count))) - break; - } - if (buf >= buf_end && !have_fire) { - DRM_ERROR("Missing Vertex Fire command or verifier " - "lost sync.\n"); - ret = 1; - break; - } - if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) { - DRM_ERROR("AGP Primitive list end misaligned.\n"); - ret = 1; - break; - } - } - *buffer = buf; - return ret; -} - -static __inline__ verifier_state_t -via_check_header2(uint32_t const **buffer, const uint32_t *buf_end, - drm_via_state_t *hc_state) -{ - uint32_t cmd; - int hz_mode; - hazard_t hz; - const uint32_t *buf = *buffer; - const hazard_t *hz_table; - - if ((buf_end - buf) < 2) { - DRM_ERROR - ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n"); - return state_error; - } - buf++; - cmd = (*buf++ & 0xFFFF0000) >> 16; - - switch (cmd) { - case HC_ParaType_CmdVdata: - if (via_check_prim_list(&buf, buf_end, hc_state)) - return state_error; - *buffer = buf; - return state_command; - case HC_ParaType_NotTex: - hz_table = table1; - break; - case HC_ParaType_Tex: - hc_state->texture = 0; - hz_table = table2; - break; - case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)): - hc_state->texture = 1; - hz_table = table2; - break; - case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)): - hz_table = table3; - break; - case HC_ParaType_Auto: - if (eat_words(&buf, buf_end, 2)) - return state_error; - *buffer = buf; - return state_command; - case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)): - if (eat_words(&buf, buf_end, 32)) - return state_error; - *buffer = buf; - return state_command; - case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)): - case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)): - DRM_ERROR("Texture palettes are rejected because of " - "lack of info how to determine their size.\n"); - return state_error; - case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)): - DRM_ERROR("Fog factor palettes are rejected because of " - "lack of info how to determine their size.\n"); - return state_error; - default: - - /* - * There are some unimplemented HC_ParaTypes here, that - * need to be implemented if the Mesa driver is extended. - */ - - DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 " - "DMA subcommand: 0x%x. Previous dword: 0x%x\n", - cmd, *(buf - 2)); - *buffer = buf; - return state_error; - } - - while (buf < buf_end) { - cmd = *buf++; - if ((hz = hz_table[cmd >> 24])) { - if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) { - if (hz_mode == 1) { - buf--; - break; - } - return state_error; - } - } else if (hc_state->unfinished && - finish_current_sequence(hc_state)) { - return state_error; - } - } - if (hc_state->unfinished && finish_current_sequence(hc_state)) - return state_error; - *buffer = buf; - return state_command; -} - -static __inline__ verifier_state_t -via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer, - const uint32_t *buf_end, int *fire_count) -{ - uint32_t cmd; - const uint32_t *buf = *buffer; - const uint32_t *next_fire; - int burst = 0; - - next_fire = dev_priv->fire_offsets[*fire_count]; - buf++; - cmd = (*buf & 0xFFFF0000) >> 16; - via_write(dev_priv, HC_REG_TRANS_SET + HC_REG_BASE, *buf++); - switch (cmd) { - case HC_ParaType_CmdVdata: - while ((buf < buf_end) && - (*fire_count < dev_priv->num_fire_offsets) && - (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) { - while (buf <= next_fire) { - via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE + - (burst & 63), *buf++); - burst += 4; - } - if ((buf < buf_end) - && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) - buf++; - - if (++(*fire_count) < dev_priv->num_fire_offsets) - next_fire = dev_priv->fire_offsets[*fire_count]; - } - break; - default: - while (buf < buf_end) { - - if (*buf == HC_HEADER2 || - (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 || - (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 || - (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) - break; - - via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE + - (burst & 63), *buf++); - burst += 4; - } - } - *buffer = buf; - return state_command; -} - -static __inline__ int verify_mmio_address(uint32_t address) -{ - if ((address > 0x3FF) && (address < 0xC00)) { - DRM_ERROR("Invalid VIDEO DMA command. " - "Attempt to access 3D- or command burst area.\n"); - return 1; - } else if ((address > 0xCFF) && (address < 0x1300)) { - DRM_ERROR("Invalid VIDEO DMA command. " - "Attempt to access PCI DMA area.\n"); - return 1; - } else if (address > 0x13FF) { - DRM_ERROR("Invalid VIDEO DMA command. " - "Attempt to access VGA registers.\n"); - return 1; - } - return 0; -} - -static __inline__ int -verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end, - uint32_t dwords) -{ - const uint32_t *buf = *buffer; - - if (buf_end - buf < dwords) { - DRM_ERROR("Illegal termination of video command.\n"); - return 1; - } - while (dwords--) { - if (*buf++) { - DRM_ERROR("Illegal video command tail.\n"); - return 1; - } - } - *buffer = buf; - return 0; -} - -static __inline__ verifier_state_t -via_check_header1(uint32_t const **buffer, const uint32_t * buf_end) -{ - uint32_t cmd; - const uint32_t *buf = *buffer; - verifier_state_t ret = state_command; - - while (buf < buf_end) { - cmd = *buf; - if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) && - (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) { - if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) - break; - DRM_ERROR("Invalid HALCYON_HEADER1 command. " - "Attempt to access 3D- or command burst area.\n"); - ret = state_error; - break; - } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) { - if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) - break; - DRM_ERROR("Invalid HALCYON_HEADER1 command. " - "Attempt to access VGA registers.\n"); - ret = state_error; - break; - } else { - buf += 2; - } - } - *buffer = buf; - return ret; -} - -static __inline__ verifier_state_t -via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer, - const uint32_t *buf_end) -{ - register uint32_t cmd; - const uint32_t *buf = *buffer; - - while (buf < buf_end) { - cmd = *buf; - if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) - break; - via_write(dev_priv, (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf); - buf++; - } - *buffer = buf; - return state_command; -} - -static __inline__ verifier_state_t -via_check_vheader5(uint32_t const **buffer, const uint32_t *buf_end) -{ - uint32_t data; - const uint32_t *buf = *buffer; - - if (buf_end - buf < 4) { - DRM_ERROR("Illegal termination of video header5 command\n"); - return state_error; - } - - data = *buf++ & ~VIA_VIDEOMASK; - if (verify_mmio_address(data)) - return state_error; - - data = *buf++; - if (*buf++ != 0x00F50000) { - DRM_ERROR("Illegal header5 header data\n"); - return state_error; - } - if (*buf++ != 0x00000000) { - DRM_ERROR("Illegal header5 header data\n"); - return state_error; - } - if (eat_words(&buf, buf_end, data)) - return state_error; - if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3))) - return state_error; - *buffer = buf; - return state_command; - -} - -static __inline__ verifier_state_t -via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer, - const uint32_t *buf_end) -{ - uint32_t addr, count, i; - const uint32_t *buf = *buffer; - - addr = *buf++ & ~VIA_VIDEOMASK; - i = count = *buf; - buf += 3; - while (i--) - via_write(dev_priv, addr, *buf++); - if (count & 3) - buf += 4 - (count & 3); - *buffer = buf; - return state_command; -} - -static __inline__ verifier_state_t -via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end) -{ - uint32_t data; - const uint32_t *buf = *buffer; - uint32_t i; - - if (buf_end - buf < 4) { - DRM_ERROR("Illegal termination of video header6 command\n"); - return state_error; - } - buf++; - data = *buf++; - if (*buf++ != 0x00F60000) { - DRM_ERROR("Illegal header6 header data\n"); - return state_error; - } - if (*buf++ != 0x00000000) { - DRM_ERROR("Illegal header6 header data\n"); - return state_error; - } - if ((buf_end - buf) < (data << 1)) { - DRM_ERROR("Illegal termination of video header6 command\n"); - return state_error; - } - for (i = 0; i < data; ++i) { - if (verify_mmio_address(*buf++)) - return state_error; - buf++; - } - data <<= 1; - if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3))) - return state_error; - *buffer = buf; - return state_command; -} - -static __inline__ verifier_state_t -via_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer, - const uint32_t *buf_end) -{ - - uint32_t addr, count, i; - const uint32_t *buf = *buffer; - - i = count = *++buf; - buf += 3; - while (i--) { - addr = *buf++; - via_write(dev_priv, addr, *buf++); - } - count <<= 1; - if (count & 3) - buf += 4 - (count & 3); - *buffer = buf; - return state_command; -} - -int -via_verify_command_stream(const uint32_t * buf, unsigned int size, - struct drm_device * dev, int agp) -{ - - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - drm_via_state_t *hc_state = &dev_priv->hc_state; - drm_via_state_t saved_state = *hc_state; - uint32_t cmd; - const uint32_t *buf_end = buf + (size >> 2); - verifier_state_t state = state_command; - int cme_video; - int supported_3d; - - cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A || - dev_priv->chipset == VIA_DX9_0); - - supported_3d = dev_priv->chipset != VIA_DX9_0; - - hc_state->dev = dev; - hc_state->unfinished = no_sequence; - hc_state->map_cache = NULL; - hc_state->agp = agp; - hc_state->buf_start = buf; - dev_priv->num_fire_offsets = 0; - - while (buf < buf_end) { - - switch (state) { - case state_header2: - state = via_check_header2(&buf, buf_end, hc_state); - break; - case state_header1: - state = via_check_header1(&buf, buf_end); - break; - case state_vheader5: - state = via_check_vheader5(&buf, buf_end); - break; - case state_vheader6: - state = via_check_vheader6(&buf, buf_end); - break; - case state_command: - cmd = *buf; - if ((cmd == HALCYON_HEADER2) && supported_3d) - state = state_header2; - else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) - state = state_header1; - else if (cme_video - && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) - state = state_vheader5; - else if (cme_video - && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) - state = state_vheader6; - else if ((cmd == HALCYON_HEADER2) && !supported_3d) { - DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n"); - state = state_error; - } else { - DRM_ERROR - ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", - cmd); - state = state_error; - } - break; - case state_error: - default: - *hc_state = saved_state; - return -EINVAL; - } - } - if (state == state_error) { - *hc_state = saved_state; - return -EINVAL; - } - return 0; -} - -int -via_parse_command_stream(struct drm_device *dev, const uint32_t *buf, - unsigned int size) -{ - - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - uint32_t cmd; - const uint32_t *buf_end = buf + (size >> 2); - verifier_state_t state = state_command; - int fire_count = 0; - - while (buf < buf_end) { - - switch (state) { - case state_header2: - state = - via_parse_header2(dev_priv, &buf, buf_end, - &fire_count); - break; - case state_header1: - state = via_parse_header1(dev_priv, &buf, buf_end); - break; - case state_vheader5: - state = via_parse_vheader5(dev_priv, &buf, buf_end); - break; - case state_vheader6: - state = via_parse_vheader6(dev_priv, &buf, buf_end); - break; - case state_command: - cmd = *buf; - if (cmd == HALCYON_HEADER2) - state = state_header2; - else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) - state = state_header1; - else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) - state = state_vheader5; - else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) - state = state_vheader6; - else { - DRM_ERROR - ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", - cmd); - state = state_error; - } - break; - case state_error: - default: - return -EINVAL; - } - } - if (state == state_error) - return -EINVAL; - return 0; -} - -static void -setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size) -{ - int i; - - for (i = 0; i < 256; ++i) - table[i] = forbidden_command; - - for (i = 0; i < size; ++i) - table[init_table[i].code] = init_table[i].hz; -} - -void via_init_command_verifier(void) -{ - setup_hazard_table(init_table1, table1, ARRAY_SIZE(init_table1)); - setup_hazard_table(init_table2, table2, ARRAY_SIZE(init_table2)); - setup_hazard_table(init_table3, table3, ARRAY_SIZE(init_table3)); -} diff --git a/drivers/gpu/drm/via/via_verifier.h b/drivers/gpu/drm/via/via_verifier.h deleted file mode 100644 index 26b6d361ab95..000000000000 --- a/drivers/gpu/drm/via/via_verifier.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2004 The Unichrome Project. All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE UNICHROME PROJECT, AND/OR ITS SUPPLIERS 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. - * - * Author: Thomas Hellström 2004. - */ - -#ifndef _VIA_VERIFIER_H_ -#define _VIA_VERIFIER_H_ - -typedef enum { - no_sequence = 0, - z_address, - dest_address, - tex_address -} drm_via_sequence_t; - -typedef struct { - unsigned texture; - uint32_t z_addr; - uint32_t d_addr; - uint32_t t_addr[2][10]; - uint32_t pitch[2][10]; - uint32_t height[2][10]; - uint32_t tex_level_lo[2]; - uint32_t tex_level_hi[2]; - uint32_t tex_palette_size[2]; - uint32_t tex_npot[2]; - drm_via_sequence_t unfinished; - int agp_texture; - int multitex; - struct drm_device *dev; - drm_local_map_t *map_cache; - uint32_t vertex_count; - int agp; - const uint32_t *buf_start; -} drm_via_state_t; - -extern int via_verify_command_stream(const uint32_t *buf, unsigned int size, - struct drm_device *dev, int agp); -extern int via_parse_command_stream(struct drm_device *dev, const uint32_t *buf, - unsigned int size); - -#endif From 685bf9f58dd9624af93d9e20e7d5353b06966a7e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:58 +0200 Subject: [PATCH 129/396] drm/via: Embed via_drv.h in via_dri1 With this change the driver is now a signle file driver. The only remaning heder file describes the HW and can be shared with the new openchrome driver. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-10-sam@ravnborg.org --- drivers/gpu/drm/via/via_dri1.c | 229 +++++++++++++++++++++++++++- drivers/gpu/drm/via/via_drv.h | 265 --------------------------------- 2 files changed, 228 insertions(+), 266 deletions(-) delete mode 100644 drivers/gpu/drm/via/via_drv.h diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index f9285cc3e1c7..d695d9291ece 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -36,13 +36,240 @@ #include <drm/drm_drv.h> #include <drm/drm_file.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_legacy.h> +#include <drm/drm_mm.h> #include <drm/drm_pciids.h> +#include <drm/drm_print.h> #include <drm/drm_vblank.h> #include <drm/via_drm.h> -#include "via_drv.h" #include "via_3d_reg.h" +#define DRIVER_AUTHOR "Various" + +#define DRIVER_NAME "via" +#define DRIVER_DESC "VIA Unichrome / Pro" +#define DRIVER_DATE "20070202" + +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 11 +#define DRIVER_PATCHLEVEL 1 + +typedef enum { + no_sequence = 0, + z_address, + dest_address, + tex_address +} drm_via_sequence_t; + +typedef struct { + unsigned texture; + uint32_t z_addr; + uint32_t d_addr; + uint32_t t_addr[2][10]; + uint32_t pitch[2][10]; + uint32_t height[2][10]; + uint32_t tex_level_lo[2]; + uint32_t tex_level_hi[2]; + uint32_t tex_palette_size[2]; + uint32_t tex_npot[2]; + drm_via_sequence_t unfinished; + int agp_texture; + int multitex; + struct drm_device *dev; + drm_local_map_t *map_cache; + uint32_t vertex_count; + int agp; + const uint32_t *buf_start; +} drm_via_state_t; + +#define VIA_PCI_BUF_SIZE 60000 +#define VIA_FIRE_BUF_SIZE 1024 +#define VIA_NUM_IRQS 4 + + +#define VIA_NUM_BLIT_ENGINES 2 +#define VIA_NUM_BLIT_SLOTS 8 + +struct _drm_via_descriptor; + +typedef struct _drm_via_sg_info { + struct page **pages; + unsigned long num_pages; + struct _drm_via_descriptor **desc_pages; + int num_desc_pages; + int num_desc; + enum dma_data_direction direction; + unsigned char *bounce_buffer; + dma_addr_t chain_start; + uint32_t free_on_sequence; + unsigned int descriptors_per_page; + int aborted; + enum { + dr_via_device_mapped, + dr_via_desc_pages_alloc, + dr_via_pages_locked, + dr_via_pages_alloc, + dr_via_sg_init + } state; +} drm_via_sg_info_t; + +typedef struct _drm_via_blitq { + struct drm_device *dev; + uint32_t cur_blit_handle; + uint32_t done_blit_handle; + unsigned serviced; + unsigned head; + unsigned cur; + unsigned num_free; + unsigned num_outstanding; + unsigned long end; + int aborting; + int is_active; + drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS]; + spinlock_t blit_lock; + wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS]; + wait_queue_head_t busy_queue; + struct work_struct wq; + struct timer_list poll_timer; +} drm_via_blitq_t; + +typedef struct drm_via_ring_buffer { + drm_local_map_t map; + char *virtual_start; +} drm_via_ring_buffer_t; + +typedef uint32_t maskarray_t[5]; + +typedef struct drm_via_irq { + atomic_t irq_received; + uint32_t pending_mask; + uint32_t enable_mask; + wait_queue_head_t irq_queue; +} drm_via_irq_t; + +typedef struct drm_via_private { + drm_via_sarea_t *sarea_priv; + drm_local_map_t *sarea; + drm_local_map_t *fb; + drm_local_map_t *mmio; + unsigned long agpAddr; + wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; + char *dma_ptr; + unsigned int dma_low; + unsigned int dma_high; + unsigned int dma_offset; + uint32_t dma_wrap; + volatile uint32_t *last_pause_ptr; + volatile uint32_t *hw_addr_ptr; + drm_via_ring_buffer_t ring; + ktime_t last_vblank; + int last_vblank_valid; + ktime_t nsec_per_vblank; + atomic_t vbl_received; + drm_via_state_t hc_state; + char pci_buf[VIA_PCI_BUF_SIZE]; + const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; + uint32_t num_fire_offsets; + int chipset; + drm_via_irq_t via_irqs[VIA_NUM_IRQS]; + unsigned num_irqs; + maskarray_t *irq_masks; + uint32_t irq_enable_mask; + uint32_t irq_pending_mask; + int *irq_map; + unsigned int idle_fault; + int vram_initialized; + struct drm_mm vram_mm; + int agp_initialized; + struct drm_mm agp_mm; + /** Mapping of userspace keys to mm objects */ + struct idr object_idr; + unsigned long vram_offset; + unsigned long agp_offset; + drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; + uint32_t dma_diff; +} drm_via_private_t; + +struct via_file_private { + struct list_head obj_list; +}; + +enum via_family { + VIA_OTHER = 0, /* Baseline */ + VIA_PRO_GROUP_A, /* Another video engine and DMA commands */ + VIA_DX9_0 /* Same video as pro_group_a, but 3D is unsupported */ +}; + +/* VIA MMIO register access */ +static inline u32 via_read(struct drm_via_private *dev_priv, u32 reg) +{ + return readl((void __iomem *)(dev_priv->mmio->handle + reg)); +} + +static inline void via_write(struct drm_via_private *dev_priv, u32 reg, + u32 val) +{ + writel(val, (void __iomem *)(dev_priv->mmio->handle + reg)); +} + +static inline void via_write8(struct drm_via_private *dev_priv, u32 reg, + u32 val) +{ + writeb(val, (void __iomem *)(dev_priv->mmio->handle + reg)); +} + +static inline void via_write8_mask(struct drm_via_private *dev_priv, + u32 reg, u32 mask, u32 val) +{ + u32 tmp; + + tmp = readb((void __iomem *)(dev_priv->mmio->handle + reg)); + tmp = (tmp & ~mask) | (val & mask); + writeb(tmp, (void __iomem *)(dev_priv->mmio->handle + reg)); +} + +/* + * Poll in a loop waiting for 'contidition' to be true. + * Note: A direct replacement with wait_event_interruptible_timeout() + * will not work unless driver is updated to emit wake_up() + * in relevant places that can impact the 'condition' + * + * Returns: + * ret keeps current value if 'condition' becomes true + * ret = -BUSY if timeout happens + * ret = -EINTR if a signal interrupted the waiting period + */ +#define VIA_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + DECLARE_WAITQUEUE(entry, current); \ + unsigned long end = jiffies + (timeout); \ + add_wait_queue(&(queue), &entry); \ + \ + for (;;) { \ + __set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (time_after_eq(jiffies, end)) { \ + ret = -EBUSY; \ + break; \ + } \ + schedule_timeout((HZ/100 > 1) ? HZ/100 : 1); \ + if (signal_pending(current)) { \ + ret = -EINTR; \ + break; \ + } \ + } \ + __set_current_state(TASK_RUNNING); \ + remove_wait_queue(&(queue), &entry); \ +} while (0) + +int via_do_cleanup_map(struct drm_device *dev); + +int via_dma_cleanup(struct drm_device *dev); +int via_driver_dma_quiescent(struct drm_device *dev); + #define CMDBUF_ALIGNMENT_SIZE (0x100) #define CMDBUF_ALIGNMENT_MASK (0x0ff) diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h deleted file mode 100644 index 640a7701f606..000000000000 --- a/drivers/gpu/drm/via/via_drv.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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. - */ -#ifndef _VIA_DRV_H_ -#define _VIA_DRV_H_ - -#include <linux/dma-mapping.h> -#include <linux/irqreturn.h> -#include <linux/jiffies.h> -#include <linux/sched.h> -#include <linux/sched/signal.h> -#include <linux/wait.h> - -#include <drm/drm_ioctl.h> -#include <drm/drm_legacy.h> -#include <drm/drm_mm.h> -#include <drm/via_drm.h> - -#define DRIVER_AUTHOR "Various" - -#define DRIVER_NAME "via" -#define DRIVER_DESC "VIA Unichrome / Pro" -#define DRIVER_DATE "20070202" - -#define DRIVER_MAJOR 2 -#define DRIVER_MINOR 11 -#define DRIVER_PATCHLEVEL 1 - -typedef enum { - no_sequence = 0, - z_address, - dest_address, - tex_address -} drm_via_sequence_t; - -typedef struct { - unsigned texture; - uint32_t z_addr; - uint32_t d_addr; - uint32_t t_addr[2][10]; - uint32_t pitch[2][10]; - uint32_t height[2][10]; - uint32_t tex_level_lo[2]; - uint32_t tex_level_hi[2]; - uint32_t tex_palette_size[2]; - uint32_t tex_npot[2]; - drm_via_sequence_t unfinished; - int agp_texture; - int multitex; - struct drm_device *dev; - drm_local_map_t *map_cache; - uint32_t vertex_count; - int agp; - const uint32_t *buf_start; -} drm_via_state_t; - -#define VIA_PCI_BUF_SIZE 60000 -#define VIA_FIRE_BUF_SIZE 1024 -#define VIA_NUM_IRQS 4 - - -#define VIA_NUM_BLIT_ENGINES 2 -#define VIA_NUM_BLIT_SLOTS 8 - -struct _drm_via_descriptor; - -typedef struct _drm_via_sg_info { - struct page **pages; - unsigned long num_pages; - struct _drm_via_descriptor **desc_pages; - int num_desc_pages; - int num_desc; - enum dma_data_direction direction; - unsigned char *bounce_buffer; - dma_addr_t chain_start; - uint32_t free_on_sequence; - unsigned int descriptors_per_page; - int aborted; - enum { - dr_via_device_mapped, - dr_via_desc_pages_alloc, - dr_via_pages_locked, - dr_via_pages_alloc, - dr_via_sg_init - } state; -} drm_via_sg_info_t; - -typedef struct _drm_via_blitq { - struct drm_device *dev; - uint32_t cur_blit_handle; - uint32_t done_blit_handle; - unsigned serviced; - unsigned head; - unsigned cur; - unsigned num_free; - unsigned num_outstanding; - unsigned long end; - int aborting; - int is_active; - drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS]; - spinlock_t blit_lock; - wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS]; - wait_queue_head_t busy_queue; - struct work_struct wq; - struct timer_list poll_timer; -} drm_via_blitq_t; - -typedef struct drm_via_ring_buffer { - drm_local_map_t map; - char *virtual_start; -} drm_via_ring_buffer_t; - -typedef uint32_t maskarray_t[5]; - -typedef struct drm_via_irq { - atomic_t irq_received; - uint32_t pending_mask; - uint32_t enable_mask; - wait_queue_head_t irq_queue; -} drm_via_irq_t; - -typedef struct drm_via_private { - drm_via_sarea_t *sarea_priv; - drm_local_map_t *sarea; - drm_local_map_t *fb; - drm_local_map_t *mmio; - unsigned long agpAddr; - wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; - char *dma_ptr; - unsigned int dma_low; - unsigned int dma_high; - unsigned int dma_offset; - uint32_t dma_wrap; - volatile uint32_t *last_pause_ptr; - volatile uint32_t *hw_addr_ptr; - drm_via_ring_buffer_t ring; - ktime_t last_vblank; - int last_vblank_valid; - ktime_t nsec_per_vblank; - atomic_t vbl_received; - drm_via_state_t hc_state; - char pci_buf[VIA_PCI_BUF_SIZE]; - const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; - uint32_t num_fire_offsets; - int chipset; - drm_via_irq_t via_irqs[VIA_NUM_IRQS]; - unsigned num_irqs; - maskarray_t *irq_masks; - uint32_t irq_enable_mask; - uint32_t irq_pending_mask; - int *irq_map; - unsigned int idle_fault; - int vram_initialized; - struct drm_mm vram_mm; - int agp_initialized; - struct drm_mm agp_mm; - /** Mapping of userspace keys to mm objects */ - struct idr object_idr; - unsigned long vram_offset; - unsigned long agp_offset; - drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; - uint32_t dma_diff; -} drm_via_private_t; - -struct via_file_private { - struct list_head obj_list; -}; - -enum via_family { - VIA_OTHER = 0, /* Baseline */ - VIA_PRO_GROUP_A, /* Another video engine and DMA commands */ - VIA_DX9_0 /* Same video as pro_group_a, but 3D is unsupported */ -}; - -/* VIA MMIO register access */ -static inline u32 via_read(struct drm_via_private *dev_priv, u32 reg) -{ - return readl((void __iomem *)(dev_priv->mmio->handle + reg)); -} - -static inline void via_write(struct drm_via_private *dev_priv, u32 reg, - u32 val) -{ - writel(val, (void __iomem *)(dev_priv->mmio->handle + reg)); -} - -static inline void via_write8(struct drm_via_private *dev_priv, u32 reg, - u32 val) -{ - writeb(val, (void __iomem *)(dev_priv->mmio->handle + reg)); -} - -static inline void via_write8_mask(struct drm_via_private *dev_priv, - u32 reg, u32 mask, u32 val) -{ - u32 tmp; - - tmp = readb((void __iomem *)(dev_priv->mmio->handle + reg)); - tmp = (tmp & ~mask) | (val & mask); - writeb(tmp, (void __iomem *)(dev_priv->mmio->handle + reg)); -} - -/* - * Poll in a loop waiting for 'contidition' to be true. - * Note: A direct replacement with wait_event_interruptible_timeout() - * will not work unless driver is updated to emit wake_up() - * in relevant places that can impact the 'condition' - * - * Returns: - * ret keeps current value if 'condition' becomes true - * ret = -BUSY if timeout happens - * ret = -EINTR if a signal interrupted the waiting period - */ -#define VIA_WAIT_ON( ret, queue, timeout, condition ) \ -do { \ - DECLARE_WAITQUEUE(entry, current); \ - unsigned long end = jiffies + (timeout); \ - add_wait_queue(&(queue), &entry); \ - \ - for (;;) { \ - __set_current_state(TASK_INTERRUPTIBLE); \ - if (condition) \ - break; \ - if (time_after_eq(jiffies, end)) { \ - ret = -EBUSY; \ - break; \ - } \ - schedule_timeout((HZ/100 > 1) ? HZ/100 : 1); \ - if (signal_pending(current)) { \ - ret = -EINTR; \ - break; \ - } \ - } \ - __set_current_state(TASK_RUNNING); \ - remove_wait_queue(&(queue), &entry); \ -} while (0) - -extern int via_init_context(struct drm_device *dev, int context); - -extern int via_do_cleanup_map(struct drm_device *dev); - -extern int via_dma_cleanup(struct drm_device *dev); -extern int via_driver_dma_quiescent(struct drm_device *dev); - -#endif From e0a49c786766ebb804592e536dab2eb97da5533f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:01:59 +0200 Subject: [PATCH 130/396] drm/via: Update to the latest via_3d_reg header Updated the 3d_reg header file to match what is used by the openchrome driver. This verifies that the two drivers can use the same header file. The file is a verbatim copy from the openchrome repo - a few style issues will be fixed in following commits. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-11-sam@ravnborg.org --- drivers/gpu/drm/via/via_3d_reg.h | 395 ++++++++++++++++++++++++------- 1 file changed, 304 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/via/via_3d_reg.h b/drivers/gpu/drm/via/via_3d_reg.h index 462375d543b9..fc74647f512a 100644 --- a/drivers/gpu/drm/via/via_3d_reg.h +++ b/drivers/gpu/drm/via/via_3d_reg.h @@ -1,6 +1,6 @@ /* - * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * Copyright 1998-2011 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2011 S3 Graphics, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -16,7 +16,7 @@ * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) 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. @@ -50,6 +50,7 @@ #define HC_ParaType_Palette 0x0003 #define HC_ParaType_PreCR 0x0010 #define HC_ParaType_Auto 0x00fe +#define INV_ParaType_Dummy 0x00300000 /* Transmission Space */ @@ -176,7 +177,7 @@ /* Command * Command A */ -#define HC_HCmdHeader_MASK 0xfe000000 /*0xffe00000 */ +#define HC_HCmdHeader_MASK 0xfe000000 /*0xffe00000 */ #define HC_HE3Fire_MASK 0x00100000 #define HC_HPMType_MASK 0x000f0000 #define HC_HEFlag_MASK 0x0000e000 @@ -236,6 +237,8 @@ /* Enable Setting */ #define HC_SubA_HEnable 0x0000 +#define HC_HenForce1P_MASK 0x00800000 /* [Force 1 Pipe] */ +#define HC_HenZDCheck_MASK 0x00400000 /* [Z dirty bit settings] */ #define HC_HenTXEnvMap_MASK 0x00200000 #define HC_HenVertexCNT_MASK 0x00100000 #define HC_HenCPUDAZ_MASK 0x00080000 @@ -682,6 +685,12 @@ #define HC_FogDenst_MASK 0x001fff00 #define HC_FogEndL_MASK 0x000000ff +/* Texture subtype definitions + */ +#define HC_SubType_Samp0 0x00000020 +#define HC_SubType_Samp1 0x00000021 + + /* Texture subtype definitions */ #define HC_SubType_Tex0 0x00000000 @@ -762,7 +771,13 @@ #define HC_SubA_HTXnBumpM10 0x0092 #define HC_SubA_HTXnBumpM11 0x0093 #define HC_SubA_HTXnLScale 0x0094 -#define HC_SubA_HTXSMD 0x0000 + +#define HC_SubA_HTXSMD 0x0000 +#define HC_SubA_HTXYUV2RGB1 0x0001 +#define HC_SubA_HTXYUV2RGB2 0x0002 +#define HC_SubA_HTXYUV2RGB3 0x0003 +#define HTXYUV2RGB4BT601 (1<<23) +#define HTXYUV2RGB4BT709 (1<<22) /* HC_SubA_HTXnL012BasH 0x0020 */ #define HC_HTXnL0BasH_MASK 0x000000ff @@ -965,6 +980,7 @@ #define HC_HTXnFM_Lum 0x00100000 #define HC_HTXnFM_Alpha 0x00180000 #define HC_HTXnFM_DX 0x00280000 +#define HC_HTXnFM_YUV 0x00300000 #define HC_HTXnFM_ARGB16 0x00880000 #define HC_HTXnFM_ARGB32 0x00980000 #define HC_HTXnFM_ABGR16 0x00a80000 @@ -995,6 +1011,12 @@ #define HC_HTXnFM_DX1 (HC_HTXnFM_DX | 0x00010000) #define HC_HTXnFM_DX23 (HC_HTXnFM_DX | 0x00020000) #define HC_HTXnFM_DX45 (HC_HTXnFM_DX | 0x00030000) +/* YUV package mode */ +#define HC_HTXnFM_YUY2 (HC_HTXnFM_YUV | 0x00000000) +/* YUV planner mode */ +#define HC_HTXnFM_YV12 (HC_HTXnFM_YUV | 0x00040000) +/* YUV planner mode */ +#define HC_HTXnFM_IYUV (HC_HTXnFM_YUV | 0x00040000) #define HC_HTXnFM_RGB555 (HC_HTXnFM_ARGB16 | 0x00000000) #define HC_HTXnFM_RGB565 (HC_HTXnFM_ARGB16 | 0x00010000) #define HC_HTXnFM_ARGB1555 (HC_HTXnFM_ARGB16 | 0x00020000) @@ -1023,6 +1045,13 @@ #define HC_HTXnLoc_Local 0x00000000 #define HC_HTXnLoc_Sys 0x00000002 #define HC_HTXnLoc_AGP 0x00000003 + +/* Video Texture */ +#define HC_HTXnYUV2RGBMode_RGB 0x00000000 +#define HC_HTXnYUV2RGBMode_SDTV 0x00000001 +#define HC_HTXnYUV2RGBMode_HDTV 0x00000002 +#define HC_HTXnYUV2RGBMode_TABLE 0x00000003 + /* HC_SubA_HTXnTRAH 0x007f */ #define HC_HTXnTRAH_MASK 0x00ff0000 @@ -1330,9 +1359,9 @@ */ #define HC_HFthRTXA_MASK 0x000000ff -/****************************************************************************** +/**************************************************************************** ** Define the Halcyon Internal register access constants. For simulator only. -******************************************************************************/ +****************************************************************************/ #define HC_SIMA_HAGPBstL 0x0000 #define HC_SIMA_HAGPBendL 0x0001 #define HC_SIMA_HAGPCMNT 0x0002 @@ -1477,80 +1506,154 @@ #define HC_SIMA_TX0TX1_OFF 0x0050 /*---- start of texture 1 setting ---- */ -#define HC_SIMA_HTX1L0BasL (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L1BasL (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L2BasL (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L3BasL (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L4BasL (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L5BasL (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6BasL (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L7BasL (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L8BasL (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L9BasL (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LaBasL (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LbBasL (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LcBasL (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LdBasL (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LeBasL (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LfBasL (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L10BasL (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L11BasL (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L012BasH (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L345BasH (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L678BasH (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L9abBasH (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LcdeBasH (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1Lf1011BasH (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0Pit (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L1Pit (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L2Pit (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L3Pit (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L4Pit (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L5Pit (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6Pit (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L7Pit (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L8Pit (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L9Pit (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LaPit (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LbPit (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LcPit (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LdPit (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LePit (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LfPit (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L10Pit (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L11Pit (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0_5WE (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6_bWE (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1Lc_11WE (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0_5HE (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6_bHE (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1Lc_11HE (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0OS (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TB (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1MPMD (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1CLODu (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1FM (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TRCH (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TRCL (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBC (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TRAH (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LTC (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LTA (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLCsat (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLCop (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLMPfog (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLAsat (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCa (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCb (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCc (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCbias (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRAa (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRFog (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM00 (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM01 (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM10 (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM11 (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LScale (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0BasL \ + (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L1BasL \ + (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L2BasL \ + (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L3BasL \ + (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L4BasL (\ + HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L5BasL \ + (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6BasL \ + (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L7BasL \ + (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L8BasL \ + (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L9BasL \ + (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LaBasL \ + (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LbBasL \ + (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LcBasL \ + (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LdBasL \ + (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LeBasL \ + (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LfBasL \ + (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L10BasL \ + (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L11BasL \ + (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L012BasH \ + (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L345BasH \ + (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L678BasH \ + (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L9abBasH \ + (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LcdeBasH \ + (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1Lf1011BasH \ + (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0Pit \ + (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L1Pit \ + (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L2Pit \ + (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L3Pit \ + (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L4Pit \ + (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L5Pit \ + (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6Pit \ + (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L7Pit \ + (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L8Pit \ + (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L9Pit \ + (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LaPit \ + (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LbPit \ + (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LcPit \ + (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LdPit \ + (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LePit \ + (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LfPit \ + (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L10Pit \ + (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L11Pit \ + (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0_5WE \ + (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6_bWE \ + (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1Lc_11WE \ + (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0_5HE \ + (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6_bHE \ + (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1Lc_11HE \ + (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0OS \ + (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TB \ + (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1MPMD \ + (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1CLODu \ + (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1FM \ + (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TRCH \ + (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TRCL \ + (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBC \ + (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TRAH \ + (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LTC \ + (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LTA \ + (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLCsat \ + (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLCop \ + (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLMPfog \ + (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLAsat \ + (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCa \ + (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCb \ + (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCc \ + (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCbias \ + (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRAa \ + (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRFog \ + (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM00 \ + (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM01 \ + (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM10 \ + (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM11 \ + (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LScale \ + (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF) /*---- end of texture 1 setting ---- 0xaf */ #define HC_SIMA_HTXSMD 0x00b0 @@ -1580,9 +1683,9 @@ #define HC_SIMA_HRErr 0x0445 #define HC_SIMA_FIFOstatus 0x0446 -/****************************************************************************** +/**************************************************************************** ** Define the AGP command header. -******************************************************************************/ +****************************************************************************/ #define HC_ACMD_MASK 0xfe000000 #define HC_ACMD_SUB_MASK 0x0c000000 #define HC_ACMD_HCmdA 0xee000000 @@ -1605,18 +1708,18 @@ #define HC_ACMD_H4COUNT_MASK 0x01fffe00 #define HC_ACMD_H4COUNT_SHIFT 9 -/******************************************************************************** +/***************************************************************************** ** Define Header -********************************************************************************/ -#define HC_HEADER2 0xF210F110 +*****************************************************************************/ +#define HC_HEADER2 0xF210F110 -/******************************************************************************** +/***************************************************************************** ** Define Dummy Value -********************************************************************************/ -#define HC_DUMMY 0xCCCCCCCC -/******************************************************************************** +*****************************************************************************/ +#define HC_DUMMY 0xCCCCCCCC +/***************************************************************************** ** Define for DMA use -********************************************************************************/ +*****************************************************************************/ #define HALCYON_HEADER2 0XF210F110 #define HALCYON_FIRECMD 0XEE100000 #define HALCYON_FIREMASK 0XFFF00000 @@ -1643,8 +1746,118 @@ #define HC_HAGPBpID_STOP 0x00000002 #define HC_HAGPBpH_MASK 0x00ffffff + #define VIA_VIDEO_HEADER5 0xFE040000 #define VIA_VIDEO_HEADER6 0xFE050000 #define VIA_VIDEO_HEADER7 0xFE060000 #define VIA_VIDEOMASK 0xFFFF0000 + +/***************************************************************************** +** Define for H5 DMA use +*****************************************************************************/ +#define H5_HC_DUMMY 0xCC000000 + +/* Command Header Type */ +#define INV_DUMMY_MASK 0xFF000000 +#define INV_AGPHeader0 0xFE000000 +#define INV_AGPHeader1 0xFE010000 +#define INV_AGPHeader2 0xFE020000 +#define INV_AGPHeader3 0xFE030000 +#define INV_AGPHeader4 0xFE040000 +#define INV_AGPHeader5 0xFE050000 +#define INV_AGPHeader6 0xFE060000 +#define INV_AGPHeader7 0xFE070000 +#define INV_AGPHeader9 0xFE090000 +#define INV_AGPHeaderA 0xFE0A0000 +#define INV_AGPHeader40 0xFE400000 +#define INV_AGPHeader41 0xFE410000 +#define INV_AGPHeader43 0xFE430000 +#define INV_AGPHeader45 0xFE450000 +#define INV_AGPHeader47 0xFE470000 +#define INV_AGPHeader4A 0xFE4A0000 +#define INV_AGPHeader82 0xFE820000 +#define INV_AGPHeader83 0xFE830000 +#define INV_AGPHeader_MASK 0xFFFF0000 +#define INV_AGPHeader2A 0xFE2A0000 +#define INV_AGPHeader25 0xFE250000 +#define INV_AGPHeader20 0xFE200000 +#define INV_AGPHeader23 0xFE230000 +#define INV_AGPHeaderE2 0xFEE20000 +#define INV_AGPHeaderE3 0xFEE30000 + +/*Transmission IO Space*/ +#define INV_REG_CR_TRANS 0x041C +#define INV_REG_CR_BEGIN 0x0420 +#define INV_REG_CR_END 0x0438 + +#define INV_REG_3D_TRANS 0x043C +#define INV_REG_3D_BEGIN 0x0440 +#define INV_REG_3D_END 0x06FC + +#define INV_ParaType_CmdVdata 0x0000 + +/* H5 Enable Setting + */ +#define INV_HC_SubA_HEnable1 0x00 + +#define INV_HC_HenAT4ALLRT_MASK 0x00100000 +#define INV_HC_HenATMRT3_MASK 0x00080000 +#define INV_HC_HenATMRT2_MASK 0x00040000 +#define INV_HC_HenATMRT1_MASK 0x00020000 +#define INV_HC_HenATMRT0_MASK 0x00010000 +#define INV_HC_HenSCMRT3_MASK 0x00008000 +#define INV_HC_HenSCMRT2_MASK 0x00004000 +#define INV_HC_HenSCMRT1_MASK 0x00002000 +#define INV_HC_HenSCMRT0_MASK 0x00001000 +#define INV_HC_HenFOGMRT3_MASK 0x00000800 +#define INV_HC_HenFOGMRT2_MASK 0x00000400 +#define INV_HC_HenFOGMRT1_MASK 0x00000200 +#define INV_HC_HenFOGMRT0_MASK 0x00000100 +#define INV_HC_HenABLMRT3_MASK 0x00000080 +#define INV_HC_HenABLMRT2_MASK 0x00000040 +#define INV_HC_HenABLMRT1_MASK 0x00000020 +#define INV_HC_HenABLMRT0_MASK 0x00000010 +#define INV_HC_HenDTMRT3_MASK 0x00000008 +#define INV_HC_HenDTMRT2_MASK 0x00000004 +#define INV_HC_HenDTMRT1_MASK 0x00000002 +#define INV_HC_HenDTMRT0_MASK 0x00000001 + +#define INV_HC_SubA_HEnable2 0x01 + +#define INV_HC_HenLUL2DR_MASK 0x00800000 +#define INV_HC_HenLDIAMOND_MASK 0x00400000 +#define INV_HC_HenPSPRITE_MASK 0x00200000 +#define INV_HC_HenC2S_MASK 0x00100000 +#define INV_HC_HenFOGPP_MASK 0x00080000 +#define INV_HC_HenSCPP_MASK 0x00040000 +#define INV_HC_HenCPP_MASK 0x00020000 +#define INV_HC_HenCZ_MASK 0x00002000 +#define INV_HC_HenVC_MASK 0x00001000 +#define INV_HC_HenCL_MASK 0x00000800 +#define INV_HC_HenPS_MASK 0x00000400 +#define INV_HC_HenWCZ_MASK 0x00000200 +#define INV_HC_HenTXCH_MASK 0x00000100 +#define INV_HC_HenBFCULL_MASK 0x00000080 +#define INV_HC_HenCW_MASK 0x00000040 +#define INV_HC_HenAA_MASK 0x00000020 +#define INV_HC_HenST_MASK 0x00000010 +#define INV_HC_HenZT_MASK 0x00000008 +#define INV_HC_HenZW_MASK 0x00000004 +#define INV_HC_HenSP_MASK 0x00000002 +#define INV_HC_HenLP_MASK 0x00000001 + +/* H5 Miscellaneous Settings + */ +#define INV_HC_SubA_HCClipTL 0x0080 +#define INV_HC_SubA_HCClipBL 0x0081 +#define INV_HC_SubA_HSClipTL 0x0082 +#define INV_HC_SubA_HSClipBL 0x0083 +#define INV_HC_SubA_HSolidCL 0x0086 +#define INV_HC_SubA_HSolidCH 0x0087 +#define INV_HC_SubA_HGBClipGL 0x0088 +#define INV_HC_SubA_HGBClipGR 0x0089 + + +#define INV_HC_ParaType_Vetex 0x00040000 + #endif From e1df7580bb2947a2fcff80d4342eb4ededbf4873 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:02:00 +0200 Subject: [PATCH 131/396] drm/via: Use SPDX tag for MIT license in via_3d_reg header The license for the via_3d_reg header is MIT - so use the shorter SPDX tag to identify the license. Suggested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-12-sam@ravnborg.org --- drivers/gpu/drm/via/via_3d_reg.h | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/gpu/drm/via/via_3d_reg.h b/drivers/gpu/drm/via/via_3d_reg.h index fc74647f512a..8796fc9fd44b 100644 --- a/drivers/gpu/drm/via/via_3d_reg.h +++ b/drivers/gpu/drm/via/via_3d_reg.h @@ -1,25 +1,7 @@ +/* SPDX-License-Identifier: MIT */ /* * Copyright 1998-2011 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2011 S3 Graphics, Inc. All Rights Reserved. - * - * 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, sub license, - * 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) 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. */ #ifndef VIA_3D_REG_H From 3579ca95759e40f3868ad5a75b4c34710858ad2b Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:02:01 +0200 Subject: [PATCH 132/396] drm/via: Make macros readable in the via_3d_reg header The macros for texture 1 setting all used continuation on a new line, resulting in a highly ureadable definition. Merge the lines so they are each on a single line. As a nice side-effect this fixes a number of checkpatch warnings: "WARNING: please, no spaces at the start of a line". Suggested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-13-sam@ravnborg.org --- drivers/gpu/drm/via/via_3d_reg.h | 222 +++++++++++-------------------- 1 file changed, 74 insertions(+), 148 deletions(-) diff --git a/drivers/gpu/drm/via/via_3d_reg.h b/drivers/gpu/drm/via/via_3d_reg.h index 8796fc9fd44b..4a884384e5b8 100644 --- a/drivers/gpu/drm/via/via_3d_reg.h +++ b/drivers/gpu/drm/via/via_3d_reg.h @@ -1488,154 +1488,80 @@ #define HC_SIMA_TX0TX1_OFF 0x0050 /*---- start of texture 1 setting ---- */ -#define HC_SIMA_HTX1L0BasL \ - (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L1BasL \ - (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L2BasL \ - (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L3BasL \ - (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L4BasL (\ - HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L5BasL \ - (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6BasL \ - (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L7BasL \ - (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L8BasL \ - (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L9BasL \ - (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LaBasL \ - (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LbBasL \ - (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LcBasL \ - (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LdBasL \ - (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LeBasL \ - (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LfBasL \ - (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L10BasL \ - (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L11BasL \ - (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L012BasH \ - (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L345BasH \ - (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L678BasH \ - (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L9abBasH \ - (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LcdeBasH \ - (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1Lf1011BasH \ - (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0Pit \ - (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L1Pit \ - (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L2Pit \ - (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L3Pit \ - (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L4Pit \ - (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L5Pit \ - (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6Pit \ - (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L7Pit \ - (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L8Pit \ - (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L9Pit \ - (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LaPit \ - (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LbPit \ - (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LcPit \ - (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LdPit \ - (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LePit \ - (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LfPit \ - (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L10Pit \ - (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L11Pit \ - (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0_5WE \ - (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6_bWE \ - (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1Lc_11WE \ - (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0_5HE \ - (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L6_bHE \ - (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1Lc_11HE \ - (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1L0OS \ - (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TB \ - (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1MPMD \ - (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1CLODu \ - (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1FM \ - (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TRCH \ - (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TRCL \ - (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBC \ - (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TRAH \ - (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LTC \ - (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LTA \ - (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLCsat \ - (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLCop \ - (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLMPfog \ - (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLAsat \ - (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCa \ - (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCb \ - (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCc \ - (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRCbias \ - (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRAa \ - (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1TBLRFog \ - (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM00 \ - (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM01 \ - (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM10 \ - (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1BumpM11 \ - (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF) -#define HC_SIMA_HTX1LScale \ - (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0BasL (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L1BasL (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L2BasL (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L3BasL (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L4BasL (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L5BasL (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6BasL (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L7BasL (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L8BasL (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L9BasL (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LaBasL (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LbBasL (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LcBasL (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LdBasL (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LeBasL (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LfBasL (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L10BasL (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L11BasL (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L012BasH (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L345BasH (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L678BasH (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L9abBasH (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LcdeBasH (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1Lf1011BasH (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0Pit (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L1Pit (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L2Pit (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L3Pit (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L4Pit (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L5Pit (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6Pit (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L7Pit (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L8Pit (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L9Pit (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LaPit (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LbPit (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LcPit (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LdPit (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LePit (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LfPit (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L10Pit (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L11Pit (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0_5WE (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6_bWE (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1Lc_11WE (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0_5HE (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L6_bHE (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1Lc_11HE (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1L0OS (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TB (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1MPMD (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1CLODu (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1FM (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TRCH (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TRCL (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBC (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TRAH (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LTC (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LTA (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLCsat (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLCop (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLMPfog (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLAsat (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCa (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCb (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCc (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRCbias (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRAa (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1TBLRFog (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM00 (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM01 (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM10 (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1BumpM11 (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF) +#define HC_SIMA_HTX1LScale (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF) /*---- end of texture 1 setting ---- 0xaf */ #define HC_SIMA_HTXSMD 0x00b0 From 5f9cfd8243ee6f69e0d82519bae463e81411f439 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Wed, 13 Jul 2022 19:02:02 +0200 Subject: [PATCH 133/396] drm/via: Fix style issues in via_3d_reg header - Fix comments using wrong style - Drop repeated word This fixes all checkpatch complains and makes the file a little bit easier to read - as the eye is not distracted by the style violations. Suggested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Kevin Brace <kevinbrace@bracecomputerlab.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220713170202.1798216-14-sam@ravnborg.org --- drivers/gpu/drm/via/via_3d_reg.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/via/via_3d_reg.h b/drivers/gpu/drm/via/via_3d_reg.h index 4a884384e5b8..eb848508b12b 100644 --- a/drivers/gpu/drm/via/via_3d_reg.h +++ b/drivers/gpu/drm/via/via_3d_reg.h @@ -156,7 +156,7 @@ #define HC_HSPXOS_SHIFT 12 #define HC_HSPYOS_MASK 0x00000fff -/* Command +/* * Command A */ #define HC_HCmdHeader_MASK 0xfe000000 /*0xffe00000 */ @@ -1342,8 +1342,8 @@ #define HC_HFthRTXA_MASK 0x000000ff /**************************************************************************** -** Define the Halcyon Internal register access constants. For simulator only. -****************************************************************************/ + * Define the Halcyon Internal register access constants. For simulator only. + ***************************************************************************/ #define HC_SIMA_HAGPBstL 0x0000 #define HC_SIMA_HAGPBendL 0x0001 #define HC_SIMA_HAGPCMNT 0x0002 @@ -1592,8 +1592,8 @@ #define HC_SIMA_FIFOstatus 0x0446 /**************************************************************************** -** Define the AGP command header. -****************************************************************************/ + * Define the AGP command header. + ***************************************************************************/ #define HC_ACMD_MASK 0xfe000000 #define HC_ACMD_SUB_MASK 0x0c000000 #define HC_ACMD_HCmdA 0xee000000 @@ -1617,17 +1617,17 @@ #define HC_ACMD_H4COUNT_SHIFT 9 /***************************************************************************** -** Define Header -*****************************************************************************/ + * Define Header + ****************************************************************************/ #define HC_HEADER2 0xF210F110 /***************************************************************************** -** Define Dummy Value -*****************************************************************************/ + * Define Dummy Value + ****************************************************************************/ #define HC_DUMMY 0xCCCCCCCC /***************************************************************************** -** Define for DMA use -*****************************************************************************/ + * Define for DMA use + ****************************************************************************/ #define HALCYON_HEADER2 0XF210F110 #define HALCYON_FIRECMD 0XEE100000 #define HALCYON_FIREMASK 0XFFF00000 @@ -1661,8 +1661,8 @@ #define VIA_VIDEOMASK 0xFFFF0000 /***************************************************************************** -** Define for H5 DMA use -*****************************************************************************/ + * Define for H5 DMA use + ****************************************************************************/ #define H5_HC_DUMMY 0xCC000000 /* Command Header Type */ From 53618649ca6ded3222b24e8d25a09be30a197577 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Thu, 16 Jun 2022 21:52:10 +0300 Subject: [PATCH 134/396] drm/fourcc: Add formats for packed YUV 4:4:4 AVUY and XVUY permutations Add FourCCs for two missing permutations of the packed YUV 4:4:4 color components, namely AVUY and XVUY. These formats are needed by the NXP i.MX8 ISI. While the ISI is supported by a V4L2 device (corresponding formats have been submitted to V4L2), it is handled in userspace by libcamera, which uses DRM FourCCs for pixel formats. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220616185210.22018-1-laurent.pinchart@ideasonboard.com --- include/uapi/drm/drm_fourcc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 3c0b165dd4ea..868d6909b718 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -229,7 +229,9 @@ extern "C" { #define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ #define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_AVUY8888 fourcc_code('A', 'V', 'U', 'Y') /* [31:0] A:Cr:Cb:Y 8:8:8:8 little endian */ #define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_XVUY8888 fourcc_code('X', 'V', 'U', 'Y') /* [31:0] X:Cr:Cb:Y 8:8:8:8 little endian */ #define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */ #define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */ From 6fc20a8592f569395aadc9fd97336facdee84f0d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas <javierm@redhat.com> Date: Sat, 18 Jun 2022 19:43:38 +0200 Subject: [PATCH 135/396] drm/ssd130x: Use new regmap bulk write support to drop custom bus Data writes for the ssd130x 4-wire SPI protocol need special handling, due the Data/Command control (D/C) pin having to be toggled prior to the write. The regmap API only allowed drivers to provide .reg_{read,write} callbacks to do per register read/write, but didn't provide a way for drivers to do the same for bulk read/writes. For this reason, a custom regmap bus was used by the driver just to define a bulk write callback that implements the D/C pin toggling. But the regmap API has been extended to support defining bulk read/write handlers, so the custom regmap bus is not needed anymore and could just be dropped. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220618174338.2253021-1-javierm@redhat.com --- drivers/gpu/drm/solomon/ssd130x-spi.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c index 07802907e39a..19ab4942cb33 100644 --- a/drivers/gpu/drm/solomon/ssd130x-spi.c +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c @@ -18,11 +18,6 @@ struct ssd130x_spi_transport { struct gpio_desc *dc; }; -static const struct regmap_config ssd130x_spi_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -}; - /* * The regmap bus .write handler, it is just a wrapper around spi_write() * but toggling the Data/Command control pin (D/C#). Since for 4-wire SPI @@ -56,17 +51,12 @@ static int ssd130x_spi_read(void *context, const void *reg, size_t reg_size, return -EOPNOTSUPP; } -/* - * A custom bus is needed due the special write that toggles a D/C# pin, - * another option could be to just have a .reg_write() callback but that - * will prevent to do data writes in bulk. - * - * Once the regmap API is extended to support defining a bulk write handler - * in the struct regmap_config, this can be simplified and the bus dropped. - */ -static struct regmap_bus regmap_ssd130x_spi_bus = { +static const struct regmap_config ssd130x_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, .write = ssd130x_spi_write, .read = ssd130x_spi_read, + .can_multi_write = true, }; static int ssd130x_spi_probe(struct spi_device *spi) @@ -90,8 +80,7 @@ static int ssd130x_spi_probe(struct spi_device *spi) t->spi = spi; t->dc = dc; - regmap = devm_regmap_init(dev, ®map_ssd130x_spi_bus, t, - &ssd130x_spi_regmap_config); + regmap = devm_regmap_init(dev, NULL, t, &ssd130x_spi_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); From fbc1fdaa8338ec4ebd862d918a0ce3e12033e8a3 Mon Sep 17 00:00:00 2001 From: Pin-Yen Lin <treapking@chromium.org> Date: Thu, 14 Jul 2022 17:39:20 +0800 Subject: [PATCH 136/396] drm/bridge: it6505: Power on downstream device in .atomic_enable Send DPCD DP_SET_POWER_D0 command to the monitor in .atomic_enable callback. Without this command, some monitors won't show up again after changing the resolution. Fixes: 46ca7da7f1e8 ("drm/bridge: it6505: Send DPCD SET_POWER to downstream") Signed-off-by: Pin-Yen Lin <treapking@chromium.org> Reviewed-by: Allen Chen <allen.chen@ite.com.tw> Fixes: 46ca7da7f1e8 ("drm/bridge: it6505: Send DPCD SET_POWER to downstream") Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220714173715.v2.1.I85af54e9ceda74ec69f661852825845f983fc343@changeid --- drivers/gpu/drm/bridge/ite-it6505.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 4b673c4792d7..e5626035f311 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -2945,6 +2945,9 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, if (ret) dev_err(dev, "Failed to setup AVI infoframe: %d", ret); + it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, + DP_SET_POWER_D0); + it6505_update_video_parameter(it6505, mode); ret = it6505_send_video_infoframe(it6505, &frame); From 899e90cf20a9d0eaec8cbc8e1ca1d05278afb6d7 Mon Sep 17 00:00:00 2001 From: allen chen <allen.chen@ite.com.tw> Date: Fri, 15 Jul 2022 10:49:05 +0800 Subject: [PATCH 137/396] drm/bridge: it6505: Modified power sequence Change power sequence to meet it6505 data sheet requirement when boot on. Signed-off-by: Pin-Yen Lin <treapking@chromium.org> Signed-off-by: Allen Chen <allen.chen@ite.com.tw> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220715024910.12578-2-allen.chen@ite.com.tw --- drivers/gpu/drm/bridge/ite-it6505.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index e5626035f311..8f5bb09ae252 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3047,7 +3047,7 @@ static int it6505_init_pdata(struct it6505 *it6505) return PTR_ERR(pdata->ovdd); } - pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(pdata->gpiod_reset)) { dev_err(dev, "gpiod_reset gpio not found"); return PTR_ERR(pdata->gpiod_reset); From 86088f88a25c76baac304b6f887e5da2c30c4e07 Mon Sep 17 00:00:00 2001 From: allen chen <allen.chen@ite.com.tw> Date: Fri, 15 Jul 2022 10:49:06 +0800 Subject: [PATCH 138/396] drm/bridge: it6505: Add i2c api power on check Use i2c bus to read/write when it6505 power off will occur i2c error. Add this check will prevent i2c error when it6505 power off. Signed-off-by: Pin-Yen Lin <treapking@chromium.org> Signed-off-by: Allen Chen <allen.chen@ite.com.tw> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220715024910.12578-3-allen.chen@ite.com.tw --- drivers/gpu/drm/bridge/ite-it6505.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 8f5bb09ae252..a30a31b21542 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -506,6 +506,9 @@ static int it6505_read(struct it6505 *it6505, unsigned int reg_addr) int err; struct device *dev = &it6505->client->dev; + if (!it6505->powered) + return -ENODEV; + err = regmap_read(it6505->regmap, reg_addr, &value); if (err < 0) { dev_err(dev, "read failed reg[0x%x] err: %d", reg_addr, err); @@ -521,6 +524,9 @@ static int it6505_write(struct it6505 *it6505, unsigned int reg_addr, int err; struct device *dev = &it6505->client->dev; + if (!it6505->powered) + return -ENODEV; + err = regmap_write(it6505->regmap, reg_addr, reg_val); if (err < 0) { @@ -538,6 +544,9 @@ static int it6505_set_bits(struct it6505 *it6505, unsigned int reg, int err; struct device *dev = &it6505->client->dev; + if (!it6505->powered) + return -ENODEV; + err = regmap_update_bits(it6505->regmap, reg, mask, value); if (err < 0) { dev_err(dev, "write reg[0x%x] = 0x%x mask = 0x%x failed err %d", @@ -2559,13 +2568,12 @@ static int it6505_poweron(struct it6505 *it6505) usleep_range(10000, 20000); } + it6505->powered = true; it6505_reset_logic(it6505); it6505_int_mask_enable(it6505); it6505_init(it6505); it6505_lane_off(it6505); - it6505->powered = true; - return 0; } From 1a217205bd2643272e32ec38926250aa6c29a854 Mon Sep 17 00:00:00 2001 From: allen chen <allen.chen@ite.com.tw> Date: Fri, 15 Jul 2022 10:49:07 +0800 Subject: [PATCH 139/396] drm/bridge: it6505: Modified video clock calculation and video debug message Speed up video clock calculation and remove redundant video debug message. Signed-off-by: Pin-Yen Lin <treapking@chromium.org> Signed-off-by: Allen Chen <allen.chen@ite.com.tw> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220715024910.12578-4-allen.chen@ite.com.tw --- drivers/gpu/drm/bridge/ite-it6505.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index a30a31b21542..f9251ec49bf0 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -691,7 +691,7 @@ static void it6505_calc_video_info(struct it6505 *it6505) DRM_DEV_DEBUG_DRIVER(dev, "hactive_start:%d, vactive_start:%d", hdes, vdes); - for (i = 0; i < 10; i++) { + for (i = 0; i < 3; i++) { it6505_set_bits(it6505, REG_DATA_CTRL0, ENABLE_PCLK_COUNTER, ENABLE_PCLK_COUNTER); usleep_range(10000, 15000); @@ -708,7 +708,7 @@ static void it6505_calc_video_info(struct it6505 *it6505) return; } - sum /= 10; + sum /= 3; pclk = 13500 * 2048 / sum; it6505->video_info.clock = pclk; it6505->video_info.hdisplay = hdew; @@ -2350,8 +2350,6 @@ static void it6505_irq_hpd(struct it6505 *it6505) if (!it6505_get_video_status(it6505)) it6505_video_reset(it6505); - - it6505_calc_video_info(it6505); } else { memset(it6505->dpcd, 0, sizeof(it6505->dpcd)); From 2b066860a4f855babd2a22f98364ff6546d85f88 Mon Sep 17 00:00:00 2001 From: shaomin Deng <dengshaomin@cdjrlc.com> Date: Mon, 18 Jul 2022 10:55:36 -0400 Subject: [PATCH 140/396] drm/mgag200:remove rebundant word "or" in comments there is a repeated word "or" in comments, so remove it. Signed-off-by: shaomin Deng <dengshaomin@cdjrlc.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220718145536.4866-1-dengshaomin@cdjrlc.com --- drivers/gpu/drm/mgag200/mgag200_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index 99a9ab7d9119..1019ffd6c260 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -96,7 +96,7 @@ #define MGAREG_SRCORG 0x2cb4 #define MGAREG_DSTORG 0x2cb8 -/* add or or this to one of the previous "power registers" to start +/* add or this to one of the previous "power registers" to start the drawing engine */ #define MGAREG_EXEC 0x0100 From 0b8613a21d9c52ccde18264b69de9f46faa362df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Tue, 12 Jul 2022 14:59:36 +0200 Subject: [PATCH 141/396] dma-buf/dma_resv_usage: update explicit sync documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make it clear that DMA_RESV_USAGE_BOOKKEEP can be used for explicit synced user space submissions as well and document the rules around adding the same fence with different usages. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Acked-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220712131201.131475-1-christian.koenig@amd.com --- include/linux/dma-resv.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index c8ccbc94d5d2..0637659a702c 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -62,6 +62,11 @@ struct dma_resv_list; * For example when asking for WRITE fences then the KERNEL fences are returned * as well. Similar when asked for READ fences then both WRITE and KERNEL * fences are returned as well. + * + * Already used fences can be promoted in the sense that a fence with + * DMA_RESV_USAGE_BOOKKEEP could become DMA_RESV_USAGE_READ by adding it again + * with this usage. But fences can never be degraded in the sense that a fence + * with DMA_RESV_USAGE_WRITE could become DMA_RESV_USAGE_READ. */ enum dma_resv_usage { /** @@ -98,10 +103,15 @@ enum dma_resv_usage { * @DMA_RESV_USAGE_BOOKKEEP: No implicit sync. * * This should be used by submissions which don't want to participate in - * implicit synchronization. + * any implicit synchronization. * - * The most common case are preemption fences as well as page table - * updates and their TLB flushes. + * The most common case are preemption fences, page table updates, TLB + * flushes as well as explicit synced user submissions. + * + * Explicit synced user user submissions can be promoted to + * DMA_RESV_USAGE_READ or DMA_RESV_USAGE_WRITE as needed using + * dma_buf_import_sync_file() when implicit synchronization should + * become necessary after initial adding of the fence. */ DMA_RESV_USAGE_BOOKKEEP }; From 71eed8a9ba8609e9c97171525c28846b9bde9a4f Mon Sep 17 00:00:00 2001 From: shaomin Deng <dengshaomin@cdjrlc.com> Date: Mon, 18 Jul 2022 11:11:54 -0400 Subject: [PATCH 142/396] drm:delete the repeated word "the" in comments remove the rebundant word "the" from comments. Signed-off-by: shaomin Deng <dengshaomin@cdjrlc.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220718151154.9628-1-dengshaomin@cdjrlc.com --- drivers/gpu/drm/display/drm_dp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index e5bab236b3ae..32b295003f49 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -1597,7 +1597,7 @@ static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg) /* * Calculate the length of the i2c transfer in usec, assuming - * the i2c bus speed is as specified. Gives the the "worst" + * the i2c bus speed is as specified. Gives the "worst" * case estimate, ie. successful while as long as possible. * Doesn't account the "MOT" bit, and instead assumes each * message includes a START, ADDRESS and STOP. Neither does it From 3475b50873e4a68302822d91ab5cb031c1a92d50 Mon Sep 17 00:00:00 2001 From: shaomin Deng <dengshaomin@cdjrlc.com> Date: Mon, 18 Jul 2022 11:04:18 -0400 Subject: [PATCH 143/396] drm:remove rebundant word "in" in comments there is a repeated word "in", so remove it. Signed-off-by: shaomin Deng <dengshaomin@cdjrlc.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220718150418.7321-1-dengshaomin@cdjrlc.com --- drivers/gpu/drm/drm_framebuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 9899bf1485b2..185b04762e2c 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -935,7 +935,7 @@ EXPORT_SYMBOL(drm_framebuffer_unregister_private); * the id and get back -EINVAL. Obviously no concern at driver unload time. * * Also, the framebuffer will not be removed from the lookup idr - for - * user-created framebuffers this will happen in in the rmfb ioctl. For + * user-created framebuffers this will happen in the rmfb ioctl. For * driver-private objects (e.g. for fbdev) drivers need to explicitly call * drm_framebuffer_unregister_private. */ From 6f481afe220d36ad7790526a2164d7fd3d5b0487 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:29 +0200 Subject: [PATCH 144/396] drm/panel/panel-sitronix-st7701: Make DSI mode flags common to ST7701 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ST7701 and ST7701S are TFT matrix drivers with integrated multi protocol decoder capable of DSI/DPI/SPI input and 480x360...864 line TFT matrix output. Currently the only supported input is DSI. The protocol decoder is separate from the TFT matrix driver and is always capable of handling all of DSI non-burst mode with sync pulses or sync events as well as DSI burst mode. Move the DSI mode configuration from TFT matrix driver properties to common ST7701 code, because this is common to all TFT matrices. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-1-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 5192d9aa572a..21a43daf5a6a 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -89,7 +89,6 @@ struct st7701_panel_desc { const struct drm_display_mode *mode; unsigned int lanes; - unsigned long flags; enum mipi_dsi_pixel_format format; const char *const *supply_names; unsigned int num_supplies; @@ -318,7 +317,6 @@ static const char * const ts8550b_supply_names[] = { static const struct st7701_panel_desc ts8550b_desc = { .mode = &ts8550b_mode, .lanes = 2, - .flags = MIPI_DSI_MODE_VIDEO, .format = MIPI_DSI_FMT_RGB888, .supply_names = ts8550b_supply_names, .num_supplies = ARRAY_SIZE(ts8550b_supply_names), @@ -336,7 +334,7 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) return -ENOMEM; desc = of_device_get_match_data(&dsi->dev); - dsi->mode_flags = desc->flags; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO; dsi->format = desc->format; dsi->lanes = desc->lanes; From a6c225be3da7edec46f96781ae07a873b2fbaa17 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:30 +0200 Subject: [PATCH 145/396] drm/panel/panel-sitronix-st7701: Enable DSI burst mode, LPM, non-continuous clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ST7701(S) is capable of DSI burst mode, which is more energy efficient than the non-burst modes. Make use of it. The ST7701(S) is capable of DSI non-continuous clock, since it sources the TFT matrix driver clock from internal clock source. The DSI non-continuous clock further reduce power utilization. The ST7701(S) uses DSI LPM for command transmissions, make sure this is configured correctly in the DSI mode flags. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-2-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 21a43daf5a6a..15cd16744406 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -334,7 +334,8 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) return -ENOMEM; desc = of_device_get_match_data(&dsi->dev); - dsi->mode_flags = MIPI_DSI_MODE_VIDEO; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS; dsi->format = desc->format; dsi->lanes = desc->lanes; From 7fa8e07128ed660c97c4a8fe615967e654b84f32 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:31 +0200 Subject: [PATCH 146/396] drm/panel/panel-sitronix-st7701: Make voltage supplies common to ST7701 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ST7701 and ST7701S all have two voltage supplies, one for internal logic and one for the TFT matrix driver. The supplies are not property of the TFT matrix driver, so move them to common ST7701 code. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-3-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 15cd16744406..8b050f2879dc 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -90,8 +90,6 @@ struct st7701_panel_desc { const struct drm_display_mode *mode; unsigned int lanes; enum mipi_dsi_pixel_format format; - const char *const *supply_names; - unsigned int num_supplies; unsigned int panel_sleep_delay; }; @@ -100,7 +98,7 @@ struct st7701 { struct mipi_dsi_device *dsi; const struct st7701_panel_desc *desc; - struct regulator_bulk_data *supplies; + struct regulator_bulk_data supplies[2]; struct gpio_desc *reset; unsigned int sleep_delay; }; @@ -200,7 +198,7 @@ static int st7701_prepare(struct drm_panel *panel) gpiod_set_value(st7701->reset, 0); - ret = regulator_bulk_enable(st7701->desc->num_supplies, + ret = regulator_bulk_enable(ARRAY_SIZE(st7701->supplies), st7701->supplies); if (ret < 0) return ret; @@ -253,7 +251,7 @@ static int st7701_unprepare(struct drm_panel *panel) */ msleep(st7701->sleep_delay); - regulator_bulk_disable(st7701->desc->num_supplies, st7701->supplies); + regulator_bulk_disable(ARRAY_SIZE(st7701->supplies), st7701->supplies); return 0; } @@ -309,17 +307,10 @@ static const struct drm_display_mode ts8550b_mode = { .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, }; -static const char * const ts8550b_supply_names[] = { - "VCC", - "IOVCC", -}; - static const struct st7701_panel_desc ts8550b_desc = { .mode = &ts8550b_mode, .lanes = 2, .format = MIPI_DSI_FMT_RGB888, - .supply_names = ts8550b_supply_names, - .num_supplies = ARRAY_SIZE(ts8550b_supply_names), .panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */ }; @@ -327,7 +318,7 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) { const struct st7701_panel_desc *desc; struct st7701 *st7701; - int ret, i; + int ret; st7701 = devm_kzalloc(&dsi->dev, sizeof(*st7701), GFP_KERNEL); if (!st7701) @@ -339,16 +330,10 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) dsi->format = desc->format; dsi->lanes = desc->lanes; - st7701->supplies = devm_kcalloc(&dsi->dev, desc->num_supplies, - sizeof(*st7701->supplies), - GFP_KERNEL); - if (!st7701->supplies) - return -ENOMEM; + st7701->supplies[0].supply = "VCC"; + st7701->supplies[1].supply = "IOVCC"; - for (i = 0; i < desc->num_supplies; i++) - st7701->supplies[i].supply = desc->supply_names[i]; - - ret = devm_regulator_bulk_get(&dsi->dev, desc->num_supplies, + ret = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(st7701->supplies), st7701->supplies); if (ret < 0) return ret; From 779c84fea3dbd658d3c4b72937732193cb01bf15 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:32 +0200 Subject: [PATCH 147/396] drm/panel/panel-sitronix-st7701: Make gamma correction TFT specific MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gamma correction values are specific to the TFT which is attached to the ST7701 TFT matrix driver, move the gamma correction values from what incorrectly looks like common init sequence into TFT matrix specific settings. While doing so, add macros which defined fields within the gamma register file and a macro which mimics FIELD_PREP except works with constant expressions. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-4-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 96 +++++++++++++++++-- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 8b050f2879dc..c5783aa7e51a 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -51,6 +51,23 @@ #define DSI_CMD2BKX_SEL_NONE 0x00 /* Command2, BK0 bytes */ +#define DSI_CMD2_BK0_GAMCTRL_AJ_MASK GENMASK(7, 6) +#define DSI_CMD2_BK0_GAMCTRL_VC0_MASK GENMASK(3, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC4_MASK GENMASK(5, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC8_MASK GENMASK(5, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC16_MASK GENMASK(4, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC24_MASK GENMASK(4, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC52_MASK GENMASK(3, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC80_MASK GENMASK(5, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC108_MASK GENMASK(3, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC147_MASK GENMASK(3, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC175_MASK GENMASK(5, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC203_MASK GENMASK(3, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC231_MASK GENMASK(4, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC239_MASK GENMASK(4, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC247_MASK GENMASK(5, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC251_MASK GENMASK(5, 0) +#define DSI_CMD2_BK0_GAMCTRL_VC255_MASK GENMASK(4, 0) #define DSI_LINESET_LINE 0x69 #define DSI_LINESET_LDE_EN BIT(7) #define DSI_LINESET_LINEDELTA GENMASK(1, 0) @@ -86,11 +103,18 @@ #define DSI_MIPISET1_EOT_EN BIT(3) #define DSI_CMD2_BK1_MIPISET1_SET (BIT(7) | DSI_MIPISET1_EOT_EN) +#define CFIELD_PREP(_mask, _val) \ + (((typeof(_mask))(_val) << (__builtin_ffsll(_mask) - 1)) & (_mask)) + struct st7701_panel_desc { const struct drm_display_mode *mode; unsigned int lanes; enum mipi_dsi_pixel_format format; unsigned int panel_sleep_delay; + + /* TFT matrix driver configuration, panel specific. */ + const u8 pv_gamma[16]; /* Positive voltage gamma control */ + const u8 nv_gamma[16]; /* Negative voltage gamma control */ }; struct st7701 { @@ -122,7 +146,8 @@ static inline int st7701_dsi_write(struct st7701 *st7701, const void *seq, static void st7701_init_sequence(struct st7701 *st7701) { - const struct drm_display_mode *mode = st7701->desc->mode; + const struct st7701_panel_desc *desc = st7701->desc; + const struct drm_display_mode *mode = desc->mode; ST7701_DSI(st7701, MIPI_DCS_SOFT_RESET, 0x00); @@ -136,12 +161,10 @@ static void st7701_init_sequence(struct st7701 *st7701) /* Command2, BK0 */ ST7701_DSI(st7701, DSI_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK0_SEL); - ST7701_DSI(st7701, DSI_CMD2_BK0_PVGAMCTRL, 0x00, 0x0E, 0x15, 0x0F, - 0x11, 0x08, 0x08, 0x08, 0x08, 0x23, 0x04, 0x13, 0x12, - 0x2B, 0x34, 0x1F); - ST7701_DSI(st7701, DSI_CMD2_BK0_NVGAMCTRL, 0x00, 0x0E, 0x95, 0x0F, - 0x13, 0x07, 0x09, 0x08, 0x08, 0x22, 0x04, 0x10, 0x0E, - 0x2C, 0x34, 0x1F); + mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_PVGAMCTRL, + desc->pv_gamma, ARRAY_SIZE(desc->pv_gamma)); + mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_NVGAMCTRL, + desc->nv_gamma, ARRAY_SIZE(desc->nv_gamma)); ST7701_DSI(st7701, DSI_CMD2_BK0_LNESET, DSI_CMD2_BK0_LNESET_B0, DSI_CMD2_BK0_LNESET_B1); ST7701_DSI(st7701, DSI_CMD2_BK0_PORCTRL, @@ -312,6 +335,65 @@ static const struct st7701_panel_desc ts8550b_desc = { .lanes = 2, .format = MIPI_DSI_FMT_RGB888, .panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */ + + .pv_gamma = { + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x8), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x23), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x12), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2b), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) + }, + .nv_gamma = { + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0x2) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x13), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x7), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x9), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x10), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) + }, }; static int st7701_dsi_probe(struct mipi_dsi_device *dsi) From 1ba85119afb5e45c699bf074dcdc894bfbf1c614 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:33 +0200 Subject: [PATCH 148/396] drm/panel/panel-sitronix-st7701: Infer vertical line count from TFT mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vertical line count is a property of the TFT matrix. Currently the driver hard-codes content of this register to specific value which is only compatible with one TFT matrix, likely the TS8550B one. Calculate the vertical line count from the mode instead. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-5-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index c5783aa7e51a..14b0ba7a1b24 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -8,6 +8,7 @@ #include <drm/drm_modes.h> #include <drm/drm_panel.h> +#include <linux/bitfield.h> #include <linux/gpio/consumer.h> #include <linux/delay.h> #include <linux/module.h> @@ -68,11 +69,9 @@ #define DSI_CMD2_BK0_GAMCTRL_VC247_MASK GENMASK(5, 0) #define DSI_CMD2_BK0_GAMCTRL_VC251_MASK GENMASK(5, 0) #define DSI_CMD2_BK0_GAMCTRL_VC255_MASK GENMASK(4, 0) -#define DSI_LINESET_LINE 0x69 -#define DSI_LINESET_LDE_EN BIT(7) -#define DSI_LINESET_LINEDELTA GENMASK(1, 0) -#define DSI_CMD2_BK0_LNESET_B1 DSI_LINESET_LINEDELTA -#define DSI_CMD2_BK0_LNESET_B0 (DSI_LINESET_LDE_EN | DSI_LINESET_LINE) +#define DSI_CMD2_BK0_LNESET_LINE_MASK GENMASK(6, 0) +#define DSI_CMD2_BK0_LNESET_LDE_EN BIT(7) +#define DSI_CMD2_BK0_LNESET_LINEDELTA GENMASK(1, 0) #define DSI_INVSEL_DEFAULT GENMASK(5, 4) #define DSI_INVSEL_NLINV GENMASK(2, 0) #define DSI_INVSEL_RTNI GENMASK(2, 1) @@ -148,6 +147,8 @@ static void st7701_init_sequence(struct st7701 *st7701) { const struct st7701_panel_desc *desc = st7701->desc; const struct drm_display_mode *mode = desc->mode; + const u8 linecount8 = mode->vdisplay / 8; + const u8 linecountrem2 = (mode->vdisplay % 8) / 2; ST7701_DSI(st7701, MIPI_DCS_SOFT_RESET, 0x00); @@ -165,8 +166,21 @@ static void st7701_init_sequence(struct st7701 *st7701) desc->pv_gamma, ARRAY_SIZE(desc->pv_gamma)); mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_NVGAMCTRL, desc->nv_gamma, ARRAY_SIZE(desc->nv_gamma)); + /* + * Vertical line count configuration: + * Line[6:0]: select number of vertical lines of the TFT matrix in + * multiples of 8 lines + * LDE_EN: enable sub-8-line granularity line count + * Line_delta[1:0]: add 0/2/4/6 extra lines to line count selected + * using Line[6:0] + * + * Total number of vertical lines: + * LN = ((Line[6:0] + 1) * 8) + (LDE_EN ? Line_delta[1:0] * 2 : 0) + */ ST7701_DSI(st7701, DSI_CMD2_BK0_LNESET, - DSI_CMD2_BK0_LNESET_B0, DSI_CMD2_BK0_LNESET_B1); + FIELD_PREP(DSI_CMD2_BK0_LNESET_LINE_MASK, linecount8 - 1) | + (linecountrem2 ? DSI_CMD2_BK0_LNESET_LDE_EN : 0), + FIELD_PREP(DSI_CMD2_BK0_LNESET_LINEDELTA, linecountrem2)); ST7701_DSI(st7701, DSI_CMD2_BK0_PORCTRL, DSI_CMD2_BK0_PORCTRL_B0(mode), DSI_CMD2_BK0_PORCTRL_B1(mode)); From 82f9cee25598a1cb06529df8e7e1f86f61e786e9 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:34 +0200 Subject: [PATCH 149/396] drm/panel/panel-sitronix-st7701: Adjust porch control bitfield name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define DSI_CMD2_BK0_PORCTRL_VBP_MASK and DSI_CMD2_BK0_PORCTRL_VFP_MASK and move the vertical back and front porch calculation from macros into the st7701_init_sequence() function, so it is clear what this does. No functional change. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-6-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 14b0ba7a1b24..ce33b362dc13 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -72,13 +72,13 @@ #define DSI_CMD2_BK0_LNESET_LINE_MASK GENMASK(6, 0) #define DSI_CMD2_BK0_LNESET_LDE_EN BIT(7) #define DSI_CMD2_BK0_LNESET_LINEDELTA GENMASK(1, 0) +#define DSI_CMD2_BK0_PORCTRL_VBP_MASK GENMASK(7, 0) +#define DSI_CMD2_BK0_PORCTRL_VFP_MASK GENMASK(7, 0) #define DSI_INVSEL_DEFAULT GENMASK(5, 4) #define DSI_INVSEL_NLINV GENMASK(2, 0) #define DSI_INVSEL_RTNI GENMASK(2, 1) #define DSI_CMD2_BK0_INVSEL_B1 DSI_INVSEL_RTNI #define DSI_CMD2_BK0_INVSEL_B0 (DSI_INVSEL_DEFAULT | DSI_INVSEL_NLINV) -#define DSI_CMD2_BK0_PORCTRL_B0(m) ((m)->vtotal - (m)->vsync_end) -#define DSI_CMD2_BK0_PORCTRL_B1(m) ((m)->vsync_start - (m)->vdisplay) /* Command2, BK1 bytes */ #define DSI_CMD2_BK1_VRHA_SET 0x45 @@ -182,8 +182,10 @@ static void st7701_init_sequence(struct st7701 *st7701) (linecountrem2 ? DSI_CMD2_BK0_LNESET_LDE_EN : 0), FIELD_PREP(DSI_CMD2_BK0_LNESET_LINEDELTA, linecountrem2)); ST7701_DSI(st7701, DSI_CMD2_BK0_PORCTRL, - DSI_CMD2_BK0_PORCTRL_B0(mode), - DSI_CMD2_BK0_PORCTRL_B1(mode)); + FIELD_PREP(DSI_CMD2_BK0_PORCTRL_VBP_MASK, + mode->vtotal - mode->vsync_end), + FIELD_PREP(DSI_CMD2_BK0_PORCTRL_VFP_MASK, + mode->vsync_start - mode->vdisplay)); ST7701_DSI(st7701, DSI_CMD2_BK0_INVSEL, DSI_CMD2_BK0_INVSEL_B0, DSI_CMD2_BK0_INVSEL_B1); From de2b4917843cd433d0f1c279123f75801dcd0c1e Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:35 +0200 Subject: [PATCH 150/396] drm/panel/panel-sitronix-st7701: Infer horizontal pixel count from TFT mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The horizontal pixel count is a property of the TFT matrix. Currently the driver hard-codes content of this register to specific value which is only compatible with one TFT matrix, likely the TS8550B one. Calculate the horizontal pixel count from the mode instead. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-7-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index ce33b362dc13..ae545eba5cb0 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -74,11 +74,9 @@ #define DSI_CMD2_BK0_LNESET_LINEDELTA GENMASK(1, 0) #define DSI_CMD2_BK0_PORCTRL_VBP_MASK GENMASK(7, 0) #define DSI_CMD2_BK0_PORCTRL_VFP_MASK GENMASK(7, 0) -#define DSI_INVSEL_DEFAULT GENMASK(5, 4) -#define DSI_INVSEL_NLINV GENMASK(2, 0) -#define DSI_INVSEL_RTNI GENMASK(2, 1) -#define DSI_CMD2_BK0_INVSEL_B1 DSI_INVSEL_RTNI -#define DSI_CMD2_BK0_INVSEL_B0 (DSI_INVSEL_DEFAULT | DSI_INVSEL_NLINV) +#define DSI_CMD2_BK0_INVSEL_ONES_MASK GENMASK(5, 4) +#define DSI_CMD2_BK0_INVSEL_NLINV_MASK GENMASK(2, 0) +#define DSI_CMD2_BK0_INVSEL_RTNI_MASK GENMASK(4, 0) /* Command2, BK1 bytes */ #define DSI_CMD2_BK1_VRHA_SET 0x45 @@ -114,6 +112,7 @@ struct st7701_panel_desc { /* TFT matrix driver configuration, panel specific. */ const u8 pv_gamma[16]; /* Positive voltage gamma control */ const u8 nv_gamma[16]; /* Negative voltage gamma control */ + const u8 nlinv; /* Inversion selection */ }; struct st7701 { @@ -186,8 +185,17 @@ static void st7701_init_sequence(struct st7701 *st7701) mode->vtotal - mode->vsync_end), FIELD_PREP(DSI_CMD2_BK0_PORCTRL_VFP_MASK, mode->vsync_start - mode->vdisplay)); + /* + * Horizontal pixel count configuration: + * PCLK = 512 + (RTNI[4:0] * 16) + * The PCLK is number of pixel clock per line, which matches + * mode htotal. The minimum is 512 PCLK. + */ ST7701_DSI(st7701, DSI_CMD2_BK0_INVSEL, - DSI_CMD2_BK0_INVSEL_B0, DSI_CMD2_BK0_INVSEL_B1); + DSI_CMD2_BK0_INVSEL_ONES_MASK | + FIELD_PREP(DSI_CMD2_BK0_INVSEL_NLINV_MASK, desc->nlinv), + FIELD_PREP(DSI_CMD2_BK0_INVSEL_RTNI_MASK, + DIV_ROUND_UP(mode->htotal, 16))); /* Command2, BK1 */ ST7701_DSI(st7701, DSI_CMD2BKX_SEL, @@ -410,6 +418,7 @@ static const struct st7701_panel_desc ts8550b_desc = { CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) }, + .nlinv = 7, }; static int st7701_dsi_probe(struct mipi_dsi_device *dsi) From 83b7a8e7e88e7a201facc9c33833330485f5ec12 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:36 +0200 Subject: [PATCH 151/396] drm/panel/panel-sitronix-st7701: Parametrize voltage and timing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of hard-coding TFT matrix voltage and timing settings, which can even lead to permanent TFT matrix damage, parametrize them in TFT matrix descriptor. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-8-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 155 ++++++++++++++---- 1 file changed, 127 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index ae545eba5cb0..e8491ac3593c 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -79,30 +79,34 @@ #define DSI_CMD2_BK0_INVSEL_RTNI_MASK GENMASK(4, 0) /* Command2, BK1 bytes */ -#define DSI_CMD2_BK1_VRHA_SET 0x45 -#define DSI_CMD2_BK1_VCOM_SET 0x13 -#define DSI_CMD2_BK1_VGHSS_SET GENMASK(2, 0) +#define DSI_CMD2_BK1_VRHA_MASK GENMASK(7, 0) +#define DSI_CMD2_BK1_VCOM_MASK GENMASK(7, 0) +#define DSI_CMD2_BK1_VGHSS_MASK GENMASK(3, 0) #define DSI_CMD2_BK1_TESTCMD_VAL BIT(7) -#define DSI_VGLS_DEFAULT BIT(6) -#define DSI_VGLS_SEL GENMASK(2, 0) -#define DSI_CMD2_BK1_VGLS_SET (DSI_VGLS_DEFAULT | DSI_VGLS_SEL) -#define DSI_PWCTLR1_AP BIT(7) /* Gamma OP bias, max */ -#define DSI_PWCTLR1_APIS BIT(2) /* Source OP input bias, min */ -#define DSI_PWCTLR1_APOS BIT(0) /* Source OP output bias, min */ -#define DSI_CMD2_BK1_PWCTLR1_SET (DSI_PWCTLR1_AP | DSI_PWCTLR1_APIS | \ - DSI_PWCTLR1_APOS) -#define DSI_PWCTLR2_AVDD BIT(5) /* AVDD 6.6v */ -#define DSI_PWCTLR2_AVCL 0x0 /* AVCL -4.4v */ -#define DSI_CMD2_BK1_PWCTLR2_SET (DSI_PWCTLR2_AVDD | DSI_PWCTLR2_AVCL) -#define DSI_SPD1_T2D BIT(3) -#define DSI_CMD2_BK1_SPD1_SET (GENMASK(6, 4) | DSI_SPD1_T2D) -#define DSI_CMD2_BK1_SPD2_SET DSI_CMD2_BK1_SPD1_SET -#define DSI_MIPISET1_EOT_EN BIT(3) -#define DSI_CMD2_BK1_MIPISET1_SET (BIT(7) | DSI_MIPISET1_EOT_EN) +#define DSI_CMD2_BK1_VGLS_ONES BIT(6) +#define DSI_CMD2_BK1_VGLS_MASK GENMASK(3, 0) +#define DSI_CMD2_BK1_PWRCTRL1_AP_MASK GENMASK(7, 6) +#define DSI_CMD2_BK1_PWRCTRL1_APIS_MASK GENMASK(3, 2) +#define DSI_CMD2_BK1_PWRCTRL1_APOS_MASK GENMASK(1, 0) +#define DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK GENMASK(5, 4) +#define DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK GENMASK(1, 0) +#define DSI_CMD2_BK1_SPD1_ONES_MASK GENMASK(6, 4) +#define DSI_CMD2_BK1_SPD1_T2D_MASK GENMASK(3, 0) +#define DSI_CMD2_BK1_SPD2_ONES_MASK GENMASK(6, 4) +#define DSI_CMD2_BK1_SPD2_T3D_MASK GENMASK(3, 0) +#define DSI_CMD2_BK1_MIPISET1_ONES BIT(7) +#define DSI_CMD2_BK1_MIPISET1_EOT_EN BIT(3) #define CFIELD_PREP(_mask, _val) \ (((typeof(_mask))(_val) << (__builtin_ffsll(_mask) - 1)) & (_mask)) +enum op_bias { + OP_BIAS_OFF = 0, + OP_BIAS_MIN, + OP_BIAS_MIDDLE, + OP_BIAS_MAX +}; + struct st7701_panel_desc { const struct drm_display_mode *mode; unsigned int lanes; @@ -113,6 +117,18 @@ struct st7701_panel_desc { const u8 pv_gamma[16]; /* Positive voltage gamma control */ const u8 nv_gamma[16]; /* Negative voltage gamma control */ const u8 nlinv; /* Inversion selection */ + const u32 vop_uv; /* Vop in uV */ + const u32 vcom_uv; /* Vcom in uV */ + const u16 vgh_mv; /* Vgh in mV */ + const s16 vgl_mv; /* Vgl in mV */ + const u16 avdd_mv; /* Avdd in mV */ + const s16 avcl_mv; /* Avcl in mV */ + const enum op_bias gamma_op_bias; + const enum op_bias input_op_bias; + const enum op_bias output_op_bias; + const u16 t2d_ns; /* T2D in ns */ + const u16 t3d_ns; /* T3D in ns */ + const bool eot_en; }; struct st7701 { @@ -142,6 +158,31 @@ static inline int st7701_dsi_write(struct st7701 *st7701, const void *seq, st7701_dsi_write(st7701, d, ARRAY_SIZE(d)); \ } +static u8 st7701_vgls_map(struct st7701 *st7701) +{ + const struct st7701_panel_desc *desc = st7701->desc; + struct { + s32 vgl; + u8 val; + } map[16] = { + { -7060, 0x0 }, { -7470, 0x1 }, + { -7910, 0x2 }, { -8140, 0x3 }, + { -8650, 0x4 }, { -8920, 0x5 }, + { -9210, 0x6 }, { -9510, 0x7 }, + { -9830, 0x8 }, { -10170, 0x9 }, + { -10530, 0xa }, { -10910, 0xb }, + { -11310, 0xc }, { -11730, 0xd }, + { -12200, 0xe }, { -12690, 0xf } + }; + int i; + + for (i = 0; i < ARRAY_SIZE(map); i++) + if (desc->vgl_mv == map[i].vgl) + return map[i].val; + + return 0; +} + static void st7701_init_sequence(struct st7701 *st7701) { const struct st7701_panel_desc *desc = st7701->desc; @@ -200,16 +241,62 @@ static void st7701_init_sequence(struct st7701 *st7701) /* Command2, BK1 */ ST7701_DSI(st7701, DSI_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK1_SEL); - ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS, DSI_CMD2_BK1_VRHA_SET); - ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM, DSI_CMD2_BK1_VCOM_SET); - ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS, DSI_CMD2_BK1_VGHSS_SET); + + /* Vop = 3.5375V + (VRHA[7:0] * 0.0125V) */ + ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS, + FIELD_PREP(DSI_CMD2_BK1_VRHA_MASK, + DIV_ROUND_CLOSEST(desc->vop_uv - 3537500, 12500))); + + /* Vcom = 0.1V + (VCOM[7:0] * 0.0125V) */ + ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM, + FIELD_PREP(DSI_CMD2_BK1_VCOM_MASK, + DIV_ROUND_CLOSEST(desc->vcom_uv - 100000, 12500))); + + /* Vgh = 11.5V + (VGHSS[7:0] * 0.5V) */ + ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS, + FIELD_PREP(DSI_CMD2_BK1_VGHSS_MASK, + DIV_ROUND_CLOSEST(clamp(desc->vgh_mv, + (u16)11500, + (u16)17000) - 11500, + 500))); + ST7701_DSI(st7701, DSI_CMD2_BK1_TESTCMD, DSI_CMD2_BK1_TESTCMD_VAL); - ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS, DSI_CMD2_BK1_VGLS_SET); - ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1, DSI_CMD2_BK1_PWCTLR1_SET); - ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2, DSI_CMD2_BK1_PWCTLR2_SET); - ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1, DSI_CMD2_BK1_SPD1_SET); - ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2, DSI_CMD2_BK1_SPD2_SET); - ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1, DSI_CMD2_BK1_MIPISET1_SET); + + /* Vgl is non-linear */ + ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS, + DSI_CMD2_BK1_VGLS_ONES | + FIELD_PREP(DSI_CMD2_BK1_VGLS_MASK, st7701_vgls_map(st7701))); + + ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1, + FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_AP_MASK, + desc->gamma_op_bias) | + FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APIS_MASK, + desc->input_op_bias) | + FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APOS_MASK, + desc->output_op_bias)); + + /* Avdd = 6.2V + (AVDD[1:0] * 0.2V) , Avcl = -4.4V - (AVCL[1:0] * 0.2V) */ + ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2, + FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK, + DIV_ROUND_CLOSEST(desc->avdd_mv - 6200, 200)) | + FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK, + DIV_ROUND_CLOSEST(-4400 + desc->avcl_mv, 200))); + + /* T2D = 0.2us * T2D[3:0] */ + ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1, + DSI_CMD2_BK1_SPD1_ONES_MASK | + FIELD_PREP(DSI_CMD2_BK1_SPD1_T2D_MASK, + DIV_ROUND_CLOSEST(desc->t2d_ns, 200))); + + /* T3D = 4us + (0.8us * T3D[3:0]) */ + ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2, + DSI_CMD2_BK1_SPD2_ONES_MASK | + FIELD_PREP(DSI_CMD2_BK1_SPD2_T3D_MASK, + DIV_ROUND_CLOSEST(desc->t3d_ns - 4000, 800))); + + ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1, + DSI_CMD2_BK1_MIPISET1_ONES | + (desc->eot_en ? DSI_CMD2_BK1_MIPISET1_EOT_EN : 0)); /** * ST7701_SPEC_V1.2 is unable to provide enough information above this @@ -419,6 +506,18 @@ static const struct st7701_panel_desc ts8550b_desc = { CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) }, .nlinv = 7, + .vop_uv = 4400000, + .vcom_uv = 337500, + .vgh_mv = 15000, + .vgl_mv = -9510, + .avdd_mv = 6600, + .avcl_mv = -4400, + .gamma_op_bias = OP_BIAS_MAX, + .input_op_bias = OP_BIAS_MIN, + .output_op_bias = OP_BIAS_MIN, + .t2d_ns = 1600, + .t3d_ns = 10400, + .eot_en = true, }; static int st7701_dsi_probe(struct mipi_dsi_device *dsi) From 42542c7904cf2e6fb795dc7ffd1903ab7d6e53fb Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 10 Jul 2022 21:44:37 +0200 Subject: [PATCH 152/396] drm/panel/panel-sitronix-st7701: Split GIP and init sequences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ST7701 initialization sequence is well parametrized, split the GIP programming sequence, which is fully custom completely undocumented TFT matrix specific magic register programming sequence into separate callback so other TFT matrix definitions can add their own GIP sequence. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-9-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index e8491ac3593c..65ee383e62fd 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -107,6 +107,8 @@ enum op_bias { OP_BIAS_MAX }; +struct st7701; + struct st7701_panel_desc { const struct drm_display_mode *mode; unsigned int lanes; @@ -129,6 +131,9 @@ struct st7701_panel_desc { const u16 t2d_ns; /* T2D in ns */ const u16 t3d_ns; /* T3D in ns */ const bool eot_en; + + /* GIP sequence, fully custom and undocumented. */ + void (*gip_sequence)(struct st7701 *st7701); }; struct st7701 { @@ -297,7 +302,10 @@ static void st7701_init_sequence(struct st7701 *st7701) ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1, DSI_CMD2_BK1_MIPISET1_ONES | (desc->eot_en ? DSI_CMD2_BK1_MIPISET1_EOT_EN : 0)); +} +static void ts8550b_gip_sequence(struct st7701 *st7701) +{ /** * ST7701_SPEC_V1.2 is unable to provide enough information above this * specific command sequence, so grab the same from vendor BSP driver. @@ -319,10 +327,6 @@ static void st7701_init_sequence(struct st7701 *st7701) ST7701_DSI(st7701, 0xEC, 0x00, 0x00); ST7701_DSI(st7701, 0xED, 0xFF, 0xF1, 0x04, 0x56, 0x72, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40, 0x1F, 0xFF); - - /* disable Command2 */ - ST7701_DSI(st7701, DSI_CMD2BKX_SEL, - 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE); } static int st7701_prepare(struct drm_panel *panel) @@ -343,6 +347,13 @@ static int st7701_prepare(struct drm_panel *panel) st7701_init_sequence(st7701); + if (st7701->desc->gip_sequence) + st7701->desc->gip_sequence(st7701); + + /* Disable Command2 */ + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, + 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE); + return 0; } @@ -518,6 +529,7 @@ static const struct st7701_panel_desc ts8550b_desc = { .t2d_ns = 1600, .t3d_ns = 10400, .eot_en = true, + .gip_sequence = ts8550b_gip_sequence, }; static int st7701_dsi_probe(struct mipi_dsi_device *dsi) From 729d6872097ffc53216430e33bc61e91c421f52b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:12 +0200 Subject: [PATCH 153/396] fbdev: Remove trailing whitespaces Fix coding style. No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-2-tzimmermann@suse.de --- drivers/video/fbdev/aty/aty128fb.c | 52 ++--- drivers/video/fbdev/aty/radeon_base.c | 66 +++--- drivers/video/fbdev/chipsfb.c | 6 +- drivers/video/fbdev/i810/i810_main.c | 310 +++++++++++++------------- drivers/video/fbdev/imsttfb.c | 28 +-- drivers/video/fbdev/neofb.c | 36 +-- drivers/video/fbdev/riva/fbdev.c | 62 +++--- drivers/video/fbdev/skeletonfb.c | 202 ++++++++--------- drivers/video/fbdev/sstfb.c | 38 ++-- drivers/video/fbdev/tgafb.c | 10 +- drivers/video/fbdev/vga16fb.c | 86 +++---- include/video/vga.h | 18 +- 12 files changed, 457 insertions(+), 457 deletions(-) diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c index b26c81233b6b..5cdbbba2a013 100644 --- a/drivers/video/fbdev/aty/aty128fb.c +++ b/drivers/video/fbdev/aty/aty128fb.c @@ -23,7 +23,7 @@ * - Convert to new framebuffer API, * fix colormap setting at 16 bits/pixel (565) * - * Paul Mundt + * Paul Mundt * - PCI hotplug * * Jon Smirl <jonsmirl@yahoo.com> @@ -520,13 +520,13 @@ static const struct fb_ops aty128fb_ops = { * - endian conversions may possibly be avoided by * using the other register aperture. TODO. */ -static inline u32 _aty_ld_le32(volatile unsigned int regindex, +static inline u32 _aty_ld_le32(volatile unsigned int regindex, const struct aty128fb_par *par) { return readl (par->regbase + regindex); } -static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, +static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, const struct aty128fb_par *par) { writel (val, par->regbase + regindex); @@ -559,12 +559,12 @@ static inline void _aty_st_8(unsigned int regindex, u8 val, static u32 _aty_ld_pll(unsigned int pll_index, const struct aty128fb_par *par) -{ +{ aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F); return aty_ld_le32(CLOCK_CNTL_DATA); } - + static void _aty_st_pll(unsigned int pll_index, u32 val, const struct aty128fb_par *par) { @@ -619,7 +619,7 @@ static int register_test(const struct aty128fb_par *par) aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA); if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA) - flag = 1; + flag = 1; } aty_st_le32(BIOS_0_SCRATCH, val); // restore value @@ -901,7 +901,7 @@ static void aty128_get_pllinfo(struct aty128fb_par *par, bios_hdr = BIOS_IN16(0x48); bios_pll = BIOS_IN16(bios_hdr + 0x30); - + par->constants.ppll_max = BIOS_IN32(bios_pll + 0x16); par->constants.ppll_min = BIOS_IN32(bios_pll + 0x12); par->constants.xclk = BIOS_IN16(bios_pll + 0x08); @@ -913,7 +913,7 @@ static void aty128_get_pllinfo(struct aty128fb_par *par, par->constants.xclk, par->constants.ref_divider, par->constants.ref_clk); -} +} #ifdef CONFIG_X86 static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par) @@ -925,7 +925,7 @@ static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par) */ u32 segstart; unsigned char __iomem *rom_base = NULL; - + for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { rom_base = ioremap(segstart, 0x10000); if (rom_base == NULL) @@ -1118,12 +1118,12 @@ static int aty128_var_to_crtc(const struct fb_var_screeninfo *var, v_sync_wid = 1; else if (v_sync_wid > 0x1f) /* 0x1f = max vwidth */ v_sync_wid = 0x1f; - + v_sync_strt = v_disp + lower; h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; - + c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8); @@ -1301,11 +1301,11 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) aty_st_le32(LVDS_GEN_CNTL, reg); #ifdef CONFIG_FB_ATY128_BACKLIGHT aty128_bl_set_power(info, FB_BLANK_UNBLANK); -#endif +#endif } else { #ifdef CONFIG_FB_ATY128_BACKLIGHT aty128_bl_set_power(info, FB_BLANK_POWERDOWN); -#endif +#endif reg = aty_ld_le32(LVDS_GEN_CNTL); reg |= LVDS_DISPLAY_DIS; aty_st_le32(LVDS_GEN_CNTL, reg); @@ -1481,7 +1481,7 @@ static int aty128_ddafifo(struct aty128_ddafifo *dsp, * This actually sets the video mode. */ static int aty128fb_set_par(struct fb_info *info) -{ +{ struct aty128fb_par *par = info->par; u32 config; int err; @@ -1595,7 +1595,7 @@ static int aty128_encode_var(struct fb_var_screeninfo *var, var->accel_flags = par->accel_flags; return 0; -} +} static int aty128fb_check_var(struct fb_var_screeninfo *var, @@ -1979,12 +1979,12 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) /* PowerBook Titanium */ if (of_machine_is_compatible("PowerBook3,2")) default_vmode = VMODE_1152_768_60; - - if (default_cmode > 16) + + if (default_cmode > 16) default_cmode = CMODE_32; - else if (default_cmode > 8) + else if (default_cmode > 8) default_cmode = CMODE_16; - else + else default_cmode = CMODE_8; if (mac_vmode_to_var(default_vmode, default_cmode, &var)) @@ -1994,7 +1994,7 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) #endif /* CONFIG_PPC_PMAC */ { if (mode_option) - if (fb_find_mode(&var, info, mode_option, NULL, + if (fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8) == 0) var = default_var; } @@ -2301,7 +2301,7 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) struct aty128fb_par *par = info->par; u32 value; int rc; - + switch (cmd) { case FBIO_ATY128_SET_MIRROR: if (par->chip_gen != rage_M3) @@ -2313,8 +2313,8 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) par->crt_on = (value & 0x02) != 0; if (!par->crt_on && !par->lcd_on) par->lcd_on = 1; - aty128_set_crt_enable(par, par->crt_on); - aty128_set_lcd_enable(par, par->lcd_on); + aty128_set_crt_enable(par, par->crt_on); + aty128_set_lcd_enable(par, par->lcd_on); return 0; case FBIO_ATY128_GET_MIRROR: if (par->chip_gen != rage_M3) @@ -2331,7 +2331,7 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) if (!par->pdev->pm_cap) return; - + /* Set the chip into the appropriate suspend mode (we use D2, * D3 would require a complete re-initialisation of the chip, * including PCI config registers, clocks, AGP configuration, ...) @@ -2376,12 +2376,12 @@ static int aty128_pci_suspend_late(struct device *dev, pm_message_t state) */ return 0; #endif /* CONFIG_PPC_PMAC */ - + if (state.event == pdev->dev.power.power_state.event) return 0; printk(KERN_DEBUG "aty128fb: suspending...\n"); - + console_lock(); fb_set_suspend(info, 1); diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index 6851f47613e1..b311c07fe66d 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -7,7 +7,7 @@ * Copyright 2000 Ani Joshi <ajoshi@kernel.crashing.org> * * i2c bits from Luca Tettamanti <kronos@kronoz.cjb.net> - * + * * Special thanks to ATI DevRel team for their hardware donations. * * ...Insert GPL boilerplate here... @@ -110,7 +110,7 @@ static const struct pci_device_id radeonfb_pci_table[] = { /* Radeon IGP320M (U1) */ CHIP_DEF(PCI_CHIP_RS100_4336, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), /* Radeon IGP320 (A3) */ - CHIP_DEF(PCI_CHIP_RS100_4136, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP), + CHIP_DEF(PCI_CHIP_RS100_4136, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP), /* IGP330M/340M/350M (U2) */ CHIP_DEF(PCI_CHIP_RS200_4337, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), /* IGP330/340/350 (A4) */ @@ -240,7 +240,7 @@ typedef struct { * interfere with anything */ static reg_val common_regs[] = { - { OVR_CLR, 0 }, + { OVR_CLR, 0 }, { OVR_WID_LEFT_RIGHT, 0 }, { OVR_WID_TOP_BOTTOM, 0 }, { OV0_SCALE_CNTL, 0 }, @@ -255,7 +255,7 @@ static reg_val common_regs[] = { /* * globals */ - + static char *mode_option; static char *monitor_layout; static bool noaccel = 0; @@ -422,7 +422,7 @@ static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) * ROM somewhere in the first meg. We will just ignore the copy * and use the ROM directly. */ - + /* Fix from ATI for problem with Radeon hardware not leaving ROM enabled */ unsigned int temp; temp = INREG(MPP_TB_CONFIG); @@ -430,14 +430,14 @@ static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) temp |= 0x04 << 24; OUTREG(MPP_TB_CONFIG, temp); temp = INREG(MPP_TB_CONFIG); - + rom = pci_map_rom(dev, &rom_size); if (!rom) { printk(KERN_ERR "radeonfb (%s): ROM failed to map\n", pci_name(rinfo->pdev)); return -ENOMEM; } - + rinfo->bios_seg = rom; /* Very simple test to make sure it appeared */ @@ -515,7 +515,7 @@ static int radeon_find_mem_vbios(struct radeonfb_info *rinfo) */ u32 segstart; void __iomem *rom_base = NULL; - + for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { rom_base = ioremap(segstart, 0x10000); if (rom_base == NULL) @@ -605,16 +605,16 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo) for(i=0; i<1000000; i++) if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0) break; - + stop_time = ktime_get(); - + local_irq_enable(); total_usecs = ktime_us_delta(stop_time, start_time); if (total_usecs >= 10 * USEC_PER_SEC || total_usecs == 0) return -1; hz = USEC_PER_SEC/(u32)total_usecs; - + hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8; vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1); vclk = (long long)hTotal * (long long)vTotal * hz; @@ -662,7 +662,7 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo) denom *= 3; break; case 6: - denom *= 6; + denom *= 6; break; case 7: denom *= 12; @@ -878,7 +878,7 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in v.green.length = 6; v.blue.length = 5; v.transp.offset = v.transp.length = 0; - break; + break; case 24: nom = 4; den = 1; @@ -908,7 +908,7 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in v.yres_virtual = v.yres; if (v.xres_virtual < v.xres) v.xres_virtual = v.xres; - + /* XXX I'm adjusting xres_virtual to the pitch, that may help XFree * with some panels, though I don't quite like this solution @@ -929,14 +929,14 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in if (v.xoffset > v.xres_virtual - v.xres) v.xoffset = v.xres_virtual - v.xres - 1; - + if (v.yoffset > v.yres_virtual - v.yres) v.yoffset = v.yres_virtual - v.yres - 1; - + v.red.msb_right = v.green.msb_right = v.blue.msb_right = v.transp.offset = v.transp.length = v.transp.msb_right = 0; - + memcpy(var, &v, sizeof(v)); return 0; @@ -951,7 +951,7 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, if ((var->xoffset + info->var.xres > info->var.xres_virtual) || (var->yoffset + info->var.yres > info->var.yres_virtual)) return -EINVAL; - + if (rinfo->asleep) return 0; @@ -1151,7 +1151,7 @@ static int radeonfb_blank (int blank, struct fb_info *info) if (rinfo->asleep) return 0; - + return radeon_screen_blank(rinfo, blank, 0); } @@ -1401,7 +1401,7 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg } else { /* R300 uses ref_div_acc field as real ref divider */ OUTPLLP(PPLL_REF_DIV, - (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), + (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), ~R300_PPLL_REF_DIV_ACC_MASK); } } else @@ -1423,7 +1423,7 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg workaround shouldn't have any effect on them. */ for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++) ; - + OUTPLL(HTOTAL_CNTL, 0); /* Clear reset & atomic update */ @@ -1510,7 +1510,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, radeon_fifo_wait(2); OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); - + return; } @@ -1735,7 +1735,7 @@ static int radeonfb_set_par(struct fb_info *info) /* Clear auto-center etc... */ newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl; newmode->crtc_more_cntl &= 0xfffffff0; - + if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN; if (mirror) @@ -1793,7 +1793,7 @@ static int radeonfb_set_par(struct fb_info *info) newmode->surface_cntl |= NONSURF_AP0_SWP_16BPP; newmode->surface_cntl |= NONSURF_AP1_SWP_16BPP; break; - case 24: + case 24: case 32: newmode->surface_cntl |= NONSURF_AP0_SWP_32BPP; newmode->surface_cntl |= NONSURF_AP1_SWP_32BPP; @@ -2028,7 +2028,7 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo) } save_crtc_gen_cntl = INREG(CRTC_GEN_CNTL); save_crtc_ext_cntl = INREG(CRTC_EXT_CNTL); - + OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl | CRTC_DISPLAY_DIS); OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B); mdelay(100); @@ -2038,7 +2038,7 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo) #ifdef SET_MC_FB_FROM_APERTURE /* Set framebuffer to be at the same address as set in PCI BAR */ - OUTREG(MC_FB_LOCATION, + OUTREG(MC_FB_LOCATION, ((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16)); rinfo->fb_local_base = aper_base; #else @@ -2079,7 +2079,7 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo) OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl); OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl); if (rinfo->has_CRTC2) - OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl); + OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl); pr_debug("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n", aper_base, @@ -2265,7 +2265,7 @@ static int radeonfb_pci_register(struct pci_dev *pdev, int err = 0; pr_debug("radeonfb_pci_register BEGIN\n"); - + /* Enable device in PCI config */ ret = pci_enable_device(pdev); if (ret < 0) { @@ -2280,9 +2280,9 @@ static int radeonfb_pci_register(struct pci_dev *pdev, goto err_disable; } rinfo = info->par; - rinfo->info = info; + rinfo->info = info; rinfo->pdev = pdev; - + spin_lock_init(&rinfo->reg_lock); timer_setup(&rinfo->lvds_timer, radeon_lvds_timer_func, 0); @@ -2521,7 +2521,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); struct radeonfb_info *rinfo = info->par; - + if (!rinfo) return; @@ -2540,7 +2540,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev) iounmap(rinfo->mmio_base); iounmap(rinfo->fb_base); - + pci_release_region(pdev, 2); pci_release_region(pdev, 0); @@ -2550,7 +2550,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev) fb_destroy_modedb(rinfo->mon1_modedb); #ifdef CONFIG_FB_RADEON_I2C radeon_delete_i2c_busses(rinfo); -#endif +#endif fb_dealloc_cmap(&info->cmap); framebuffer_release(info); } diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c index 393894af26f8..618fb6dbbedb 100644 --- a/drivers/video/fbdev/chipsfb.c +++ b/drivers/video/fbdev/chipsfb.c @@ -122,7 +122,7 @@ static int chipsfb_set_par(struct fb_info *info) info->var.blue.offset = 0; info->var.red.length = info->var.green.length = info->var.blue.length = 5; - + } else { /* p->var.bits_per_pixel == 8 */ write_cr(0x13, 100); // Set line length (doublewords) @@ -131,13 +131,13 @@ static int chipsfb_set_par(struct fb_info *info) write_xr(0x20, 0x00); // 8 bit blitter mode info->fix.line_length = 800; - info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; info->var.red.offset = info->var.green.offset = info->var.blue.offset = 0; info->var.red.length = info->var.green.length = info->var.blue.length = 8; - + } return 0; } diff --git a/drivers/video/fbdev/i810/i810_main.c b/drivers/video/fbdev/i810/i810_main.c index 13bbf7fe13bf..41a86efca516 100644 --- a/drivers/video/fbdev/i810/i810_main.c +++ b/drivers/video/fbdev/i810/i810_main.c @@ -2,12 +2,12 @@ * linux/drivers/video/i810_main.c -- Intel 810 frame buffer device * * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net> - * All Rights Reserved + * All Rights Reserved * * Contributors: * Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets - * and enabling the power-on state of - * external VGA connectors for + * and enabling the power-on state of + * external VGA connectors for * secondary displays * * Fredrik Andersson <krueger@shell.linux.se> - alpha testing of @@ -17,10 +17,10 @@ * timings support * * The code framework is a modification of vfb.c by Geert Uytterhoeven. - * DotClock and PLL calculations are partly based on i810_driver.c + * DotClock and PLL calculations are partly based on i810_driver.c * in xfree86 v4.0.3 by Precision Insight. - * Watermark calculation and tables are based on i810_wmark.c - * in xfre86 v4.0.3 by Precision Insight. Slight modifications + * Watermark calculation and tables are based on i810_wmark.c + * in xfre86 v4.0.3 by Precision Insight. Slight modifications * only to allow for integer operations instead of floating point. * * This file is subject to the terms and conditions of the GNU General Public @@ -204,8 +204,8 @@ static void i810_dram_off(u8 __iomem *mmio, u8 mode) * @mode: protect/unprotect * * DESCRIPTION: - * The IBM VGA standard allows protection of certain VGA registers. - * This will protect or unprotect them. + * The IBM VGA standard allows protection of certain VGA registers. + * This will protect or unprotect them. */ static void i810_protect_regs(u8 __iomem *mmio, int mode) { @@ -215,7 +215,7 @@ static void i810_protect_regs(u8 __iomem *mmio, int mode) reg = i810_readb(CR_DATA_CGA, mmio); reg = (mode == OFF) ? reg & ~0x80 : reg | 0x80; - + i810_writeb(CR_INDEX_CGA, mmio, CR11); i810_writeb(CR_DATA_CGA, mmio, reg); } @@ -225,18 +225,18 @@ static void i810_protect_regs(u8 __iomem *mmio, int mode) * @par: pointer to i810fb_par structure * * DESCRIPTION: - * Loads the P, M, and N registers. + * Loads the P, M, and N registers. */ static void i810_load_pll(struct i810fb_par *par) { u32 tmp1, tmp2; u8 __iomem *mmio = par->mmio_start_virtual; - + tmp1 = par->regs.M | par->regs.N << 16; tmp2 = i810_readl(DCLK_2D, mmio); tmp2 &= ~MN_MASK; i810_writel(DCLK_2D, mmio, tmp1 | tmp2); - + tmp1 = par->regs.P; tmp2 = i810_readl(DCLK_0DS, mmio); tmp2 &= ~(P_OR << 16); @@ -254,7 +254,7 @@ static void i810_load_pll(struct i810fb_par *par) * Load values to VGA registers */ static void i810_load_vga(struct i810fb_par *par) -{ +{ u8 __iomem *mmio = par->mmio_start_virtual; /* interlace */ @@ -327,7 +327,7 @@ static void i810_load_2d(struct i810fb_par *par) u8 tmp8; u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(FW_BLC, mmio, par->watermark); + i810_writel(FW_BLC, mmio, par->watermark); tmp = i810_readl(PIXCONF, mmio); tmp |= 1 | 1 << 20; i810_writel(PIXCONF, mmio, tmp); @@ -339,7 +339,7 @@ static void i810_load_2d(struct i810fb_par *par) tmp8 |= 2; i810_writeb(GR_INDEX, mmio, GR10); i810_writeb(GR_DATA, mmio, tmp8); -} +} /** * i810_hires - enables high resolution mode @@ -348,7 +348,7 @@ static void i810_load_2d(struct i810fb_par *par) static void i810_hires(u8 __iomem *mmio) { u8 val; - + i810_writeb(CR_INDEX_CGA, mmio, CR80); val = i810_readb(CR_DATA_CGA, mmio); i810_writeb(CR_INDEX_CGA, mmio, CR80); @@ -363,13 +363,13 @@ static void i810_hires(u8 __iomem *mmio) * * DESCRIPTION: * Loads the characters per line - */ + */ static void i810_load_pitch(struct i810fb_par *par) { u32 tmp, pitch; u8 val; u8 __iomem *mmio = par->mmio_start_virtual; - + pitch = par->pitch >> 3; i810_writeb(SR_INDEX, mmio, SR01); val = i810_readb(SR_DATA, mmio); @@ -381,7 +381,7 @@ static void i810_load_pitch(struct i810fb_par *par) tmp = pitch & 0xFF; i810_writeb(CR_INDEX_CGA, mmio, CR13); i810_writeb(CR_DATA_CGA, mmio, (u8) tmp); - + tmp = pitch >> 8; i810_writeb(CR_INDEX_CGA, mmio, CR41); val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F; @@ -414,7 +414,7 @@ static void i810_load_color(struct i810fb_par *par) /** * i810_load_regs - loads all registers for the mode * @par: pointer to i810fb_par structure - * + * * DESCRIPTION: * Loads registers */ @@ -428,7 +428,7 @@ static void i810_load_regs(struct i810fb_par *par) i810_load_pll(par); i810_load_vga(par); i810_load_vgax(par); - i810_dram_off(mmio, ON); + i810_dram_off(mmio, ON); i810_load_2d(par); i810_hires(mmio); i810_screen_off(mmio, ON); @@ -443,7 +443,7 @@ static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue, i810_writeb(CLUT_INDEX_WRITE, mmio, regno); i810_writeb(CLUT_DATA, mmio, red); i810_writeb(CLUT_DATA, mmio, green); - i810_writeb(CLUT_DATA, mmio, blue); + i810_writeb(CLUT_DATA, mmio, blue); } static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue, @@ -456,13 +456,13 @@ static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue, } /************************************************************ - * VGA State Restore * + * VGA State Restore * ************************************************************/ static void i810_restore_pll(struct i810fb_par *par) { u32 tmp1, tmp2; u8 __iomem *mmio = par->mmio_start_virtual; - + tmp1 = par->hw_state.dclk_2d; tmp2 = i810_readl(DCLK_2D, mmio); tmp1 &= ~MN_MASK; @@ -494,7 +494,7 @@ static void i810_restore_vgax(struct i810fb_par *par) { u8 i, j; u8 __iomem *mmio = par->mmio_start_virtual; - + for (i = 0; i < 4; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR30+i); i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i)); @@ -528,7 +528,7 @@ static void i810_restore_vga(struct i810fb_par *par) { u8 i; u8 __iomem *mmio = par->mmio_start_virtual; - + for (i = 0; i < 10; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR00 + i); i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i)); @@ -559,10 +559,10 @@ static void i810_restore_2d(struct i810fb_par *par) u8 __iomem *mmio = par->mmio_start_virtual; tmp_word = i810_readw(BLTCNTL, mmio); - tmp_word &= ~(3 << 4); + tmp_word &= ~(3 << 4); tmp_word |= par->hw_state.bltcntl; i810_writew(BLTCNTL, mmio, tmp_word); - + i810_dram_off(mmio, OFF); i810_writel(PIXCONF, mmio, par->hw_state.pixconf); i810_dram_off(mmio, ON); @@ -577,7 +577,7 @@ static void i810_restore_2d(struct i810fb_par *par) tmp_long |= par->hw_state.fw_blc; i810_writel(FW_BLC, mmio, tmp_long); - i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga); + i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga); i810_writew(IER, mmio, par->hw_state.ier); i810_writew(IMR, mmio, par->hw_state.imr); i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas); @@ -621,7 +621,7 @@ static void i810_save_vgax(struct i810fb_par *par) i810_writeb(CR_INDEX_CGA, mmio, CR41); par->hw_state.cr41 = i810_readb(CR_DATA_CGA, mmio); i810_writeb(CR_INDEX_CGA, mmio, CR70); - par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio); + par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio); par->hw_state.msr = i810_readb(MSR_READ, mmio); i810_writeb(CR_INDEX_CGA, mmio, CR80); par->hw_state.cr80 = i810_readb(CR_DATA_CGA, mmio); @@ -654,8 +654,8 @@ static void i810_save_2d(struct i810fb_par *par) par->hw_state.pixconf = i810_readl(PIXCONF, mmio); par->hw_state.fw_blc = i810_readl(FW_BLC, mmio); par->hw_state.bltcntl = i810_readw(BLTCNTL, mmio); - par->hw_state.hwstam = i810_readw(HWSTAM, mmio); - par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio); + par->hw_state.hwstam = i810_readw(HWSTAM, mmio); + par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio); par->hw_state.ier = i810_readw(IER, mmio); par->hw_state.imr = i810_readw(IMR, mmio); par->hw_state.dplystas = i810_readl(DPLYSTAS, mmio); @@ -669,7 +669,7 @@ static void i810_save_vga_state(struct i810fb_par *par) } /************************************************************ - * Helpers * + * Helpers * ************************************************************/ /** * get_line_length - calculates buffer pitch in bytes @@ -678,12 +678,12 @@ static void i810_save_vga_state(struct i810fb_par *par) * @bpp: bits per pixel * * DESCRIPTION: - * Calculates buffer pitch in bytes. + * Calculates buffer pitch in bytes. */ static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp) { u32 length; - + length = xres_virtual*bpp; length = (length+31)&-32; length >>= 3; @@ -716,17 +716,17 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p) n_target_max = 30; /* - * find P such that target freq is 16x reference freq (Hz). + * find P such that target freq is 16x reference freq (Hz). */ p_divisor = 1; p_target = 0; - while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) && + while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) && p_divisor <= 32) { p_divisor <<= 1; p_target++; } - n_reg = m_reg = n_target = 3; + n_reg = m_reg = n_target = 3; while (diff_min && mod_min && (n_target < n_target_max)) { f_out = (p_divisor * n_reg * 1000000)/(4 * 24 * m_reg); mod = (p_divisor * n_reg * 1000000) % (4 * 24 * m_reg); @@ -744,14 +744,14 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p) diff_min = diff; n_best = n_target; m_best = m_target; - } + } if (!diff && mod_min > mod) { mod_min = mod; n_best = n_target; m_best = m_target; } - } + } if (m) *m = (m_best - 2) & 0x3FF; if (n) *n = (n_best - 2) & 0x3FF; if (p) *p = (p_target << 4); @@ -772,7 +772,7 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p) static void i810_enable_cursor(u8 __iomem *mmio, int mode) { u32 temp; - + temp = i810_readl(PIXCONF, mmio); temp = (mode == ON) ? temp | CURSOR_ENABLE_MASK : temp & ~CURSOR_ENABLE_MASK; @@ -786,10 +786,10 @@ static void i810_reset_cursor_image(struct i810fb_par *par) int i, j; for (i = 64; i--; ) { - for (j = 0; j < 8; j++) { - i810_writeb(j, addr, 0xff); - i810_writeb(j+8, addr, 0x00); - } + for (j = 0; j < 8; j++) { + i810_writeb(j, addr, 0xff); + i810_writeb(j+8, addr, 0x00); + } addr +=16; } } @@ -800,9 +800,9 @@ static void i810_load_cursor_image(int width, int height, u8 *data, u8 __iomem *addr = par->cursor_heap.virtual; int i, j, w = width/8; int mod = width % 8, t_mask, d_mask; - + t_mask = 0xff >> mod; - d_mask = ~(0xff >> mod); + d_mask = ~(0xff >> mod); for (i = height; i--; ) { for (j = 0; j < w; j++) { i810_writeb(j+0, addr, 0x00); @@ -854,7 +854,7 @@ static void i810_init_cursor(struct i810fb_par *par) i810_enable_cursor(mmio, OFF); i810_writel(CURBASE, mmio, par->cursor_heap.physical); i810_writew(CURCNTR, mmio, COORD_ACTIVE | CURSOR_MODE_64_XOR); -} +} /********************************************************************* * Framebuffer hook helpers * @@ -873,7 +873,7 @@ static void i810_round_off(struct fb_var_screeninfo *var) u32 xres, yres, vxres, vyres; /* - * Presently supports only these configurations + * Presently supports only these configurations */ xres = var->xres; @@ -883,20 +883,20 @@ static void i810_round_off(struct fb_var_screeninfo *var) var->bits_per_pixel += 7; var->bits_per_pixel &= ~7; - + if (var->bits_per_pixel < 8) var->bits_per_pixel = 8; - if (var->bits_per_pixel > 32) + if (var->bits_per_pixel > 32) var->bits_per_pixel = 32; round_off_xres(&xres); if (xres < 40) xres = 40; - if (xres > 2048) + if (xres > 2048) xres = 2048; xres = (xres + 7) & ~7; - if (vxres < xres) + if (vxres < xres) vxres = xres; round_off_yres(&xres, &yres); @@ -905,7 +905,7 @@ static void i810_round_off(struct fb_var_screeninfo *var) if (yres >= 2048) yres = 2048; - if (vyres < yres) + if (vyres < yres) vyres = yres; if (var->bits_per_pixel == 32) @@ -917,30 +917,30 @@ static void i810_round_off(struct fb_var_screeninfo *var) var->hsync_len = (var->hsync_len + 4) & ~7; if (var->vmode & FB_VMODE_INTERLACED) { - if (!((yres + var->upper_margin + var->vsync_len + + if (!((yres + var->upper_margin + var->vsync_len + var->lower_margin) & 1)) var->upper_margin++; } - + var->xres = xres; var->yres = yres; var->xres_virtual = vxres; var->yres_virtual = vyres; -} +} /** * set_color_bitfields - sets rgba fields * @var: pointer to fb_var_screeninfo * * DESCRIPTION: - * The length, offset and ordering for each color field - * (red, green, blue) will be set as specified + * The length, offset and ordering for each color field + * (red, green, blue) will be set as specified * by the hardware - */ + */ static void set_color_bitfields(struct fb_var_screeninfo *var) { switch (var->bits_per_pixel) { - case 8: + case 8: var->red.offset = 0; var->red.length = 8; var->green.offset = 0; @@ -984,11 +984,11 @@ static void set_color_bitfields(struct fb_var_screeninfo *var) * @info: pointer to fb_info * * DESCRIPTION: - * This will check if the framebuffer size is sufficient - * for the current mode and if the user's monitor has the + * This will check if the framebuffer size is sufficient + * for the current mode and if the user's monitor has the * required specifications to display the current mode. */ -static int i810_check_params(struct fb_var_screeninfo *var, +static int i810_check_params(struct fb_var_screeninfo *var, struct fb_info *info) { struct i810fb_par *par = info->par; @@ -1007,14 +1007,14 @@ static int i810_check_params(struct fb_var_screeninfo *var, vyres = info->var.yres; vxres = par->fb.size/vyres; vxres /= var->bits_per_pixel >> 3; - line_length = get_line_length(par, vxres, + line_length = get_line_length(par, vxres, var->bits_per_pixel); vidmem = line_length * info->var.yres; if (vxres < var->xres) { printk("i810fb: required video memory, " "%d bytes, for %dx%d-%d (virtual) " - "is out of range\n", - vidmem, vxres, vyres, + "is out of range\n", + vidmem, vxres, vyres, var->bits_per_pixel); return -ENOMEM; } @@ -1074,7 +1074,7 @@ static int i810_check_params(struct fb_var_screeninfo *var, } return retval; -} +} /** * encode_fix - fill up fb_fix_screeninfo structure @@ -1131,9 +1131,9 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) * * DESCRIPTION: * Based on the contents of @var, @par will be dynamically filled up. - * @par contains all information necessary to modify the hardware. + * @par contains all information necessary to modify the hardware. */ -static void decode_var(const struct fb_var_screeninfo *var, +static void decode_var(const struct fb_var_screeninfo *var, struct i810fb_par *par) { u32 xres, yres, vxres, vyres; @@ -1175,13 +1175,13 @@ static void decode_var(const struct fb_var_screeninfo *var, if (var->nonstd && var->bits_per_pixel != 8) par->pixconf |= 1 << 27; - i810_calc_dclk(var->pixclock, &par->regs.M, + i810_calc_dclk(var->pixclock, &par->regs.M, &par->regs.N, &par->regs.P); i810fb_encode_registers(var, par, xres, yres); par->watermark = i810_get_watermark(var, par); par->pitch = get_line_length(par, vxres, var->bits_per_pixel); -} +} /** * i810fb_getcolreg - gets red, green and blue values of the hardware DAC @@ -1196,7 +1196,7 @@ static void decode_var(const struct fb_var_screeninfo *var, * Gets the red, green and blue values of the hardware DAC as pointed by @regno * and writes them to @red, @green and @blue respectively */ -static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, +static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, u8 *transp, struct fb_info *info) { struct i810fb_par *par = info->par; @@ -1212,18 +1212,18 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, temp = i810_readb(PIXCONF1, mmio); i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE); - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && - info->var.green.length == 5) + if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && + info->var.green.length == 5) i810_read_dac(regno * 8, red, green, blue, mmio); - else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && + else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && info->var.green.length == 6) { u8 tmp; i810_read_dac(regno * 8, red, &tmp, blue, mmio); i810_read_dac(regno * 4, &tmp, green, &tmp, mmio); } - else + else i810_read_dac(regno, red, green, blue, mmio); *transp = 0; @@ -1232,7 +1232,7 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, return 0; } -/****************************************************************** +/****************************************************************** * Framebuffer device-specific hooks * ******************************************************************/ @@ -1252,7 +1252,7 @@ static int i810fb_open(struct fb_info *info, int user) par->use_count++; mutex_unlock(&par->open_lock); - + return 0; } @@ -1273,13 +1273,13 @@ static int i810fb_release(struct fb_info *info, int user) par->use_count--; mutex_unlock(&par->open_lock); - + return 0; } -static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, +static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *info) { struct i810fb_par *par = info->par; @@ -1302,24 +1302,24 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, temp = i810_readb(PIXCONF1, mmio); i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE); - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && + if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && info->var.green.length == 5) { - for (i = 0; i < 8; i++) - i810_write_dac((u8) (regno * 8) + i, (u8) red, + for (i = 0; i < 8; i++) + i810_write_dac((u8) (regno * 8) + i, (u8) red, (u8) green, (u8) blue, mmio); - } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && + } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && info->var.green.length == 6) { u8 r, g, b; if (regno < 32) { - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) i810_write_dac((u8) (regno * 8) + i, - (u8) red, (u8) green, + (u8) red, (u8) green, (u8) blue, mmio); } i810_read_dac((u8) (regno*4), &r, &g, &b, mmio); - for (i = 0; i < 4; i++) - i810_write_dac((u8) (regno*4) + i, r, (u8) green, + for (i = 0; i < 4; i++) + i810_write_dac((u8) (regno*4) + i, r, (u8) green, b, mmio); } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { i810_write_dac((u8) regno, (u8) red, (u8) green, @@ -1330,20 +1330,20 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, if (regno < 16) { switch (info->var.bits_per_pixel) { - case 16: + case 16: if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - if (info->var.green.length == 5) - ((u32 *)info->pseudo_palette)[regno] = + if (info->var.green.length == 5) + ((u32 *)info->pseudo_palette)[regno] = (regno << 10) | (regno << 5) | regno; else - ((u32 *)info->pseudo_palette)[regno] = + ((u32 *)info->pseudo_palette)[regno] = (regno << 11) | (regno << 5) | regno; } else { if (info->var.green.length == 5) { /* RGB 555 */ - ((u32 *)info->pseudo_palette)[regno] = + ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); @@ -1358,12 +1358,12 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, break; case 24: /* RGB 888 */ case 32: /* RGBA 8888 */ - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) - ((u32 *)info->pseudo_palette)[regno] = + if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) + ((u32 *)info->pseudo_palette)[regno] = (regno << 16) | (regno << 8) | regno; - else - ((u32 *)info->pseudo_palette)[regno] = + else + ((u32 *)info->pseudo_palette)[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | ((blue & 0xff00) >> 8); @@ -1373,13 +1373,13 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, return 0; } -static int i810fb_pan_display(struct fb_var_screeninfo *var, +static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct i810fb_par *par = info->par; u32 total; - - total = var->xoffset * par->depth + + + total = var->xoffset * par->depth + var->yoffset * info->fix.line_length; i810fb_load_front(total, info); @@ -1391,7 +1391,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info) struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; int mode = 0, pwr, scr_off = 0; - + pwr = i810_readl(PWR_CLKC, mmio); switch (blank_mode) { @@ -1421,7 +1421,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info) scr_off = OFF; break; default: - return -EINVAL; + return -EINVAL; } i810_screen_off(mmio, scr_off); @@ -1452,7 +1452,7 @@ static int i810fb_set_par(struct fb_info *info) return 0; } -static int i810fb_check_var(struct fb_var_screeninfo *var, +static int i810fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int err; @@ -1550,7 +1550,7 @@ static const struct fb_ops i810fb_ops = { .fb_set_par = i810fb_set_par, .fb_setcolreg = i810fb_setcolreg, .fb_blank = i810fb_blank, - .fb_pan_display = i810fb_pan_display, + .fb_pan_display = i810fb_pan_display, .fb_fillrect = i810fb_fillrect, .fb_copyarea = i810fb_copyarea, .fb_imageblit = i810fb_imageblit, @@ -1593,7 +1593,7 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg) return 0; } -static int i810fb_resume(struct pci_dev *dev) +static int i810fb_resume(struct pci_dev *dev) { struct fb_info *info = pci_get_drvdata(dev); struct i810fb_par *par = info->par; @@ -1628,14 +1628,14 @@ fail: /*********************************************************************** * AGP resource allocation * ***********************************************************************/ - + static void i810_fix_pointers(struct i810fb_par *par) { par->fb.physical = par->aperture.physical+(par->fb.offset << 12); par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12); - par->iring.physical = par->aperture.physical + + par->iring.physical = par->aperture.physical + (par->iring.offset << 12); - par->iring.virtual = par->aperture.virtual + + par->iring.virtual = par->aperture.virtual + (par->iring.offset << 12); par->cursor_heap.virtual = par->aperture.virtual+ (par->cursor_heap.offset << 12); @@ -1666,7 +1666,7 @@ static int i810_alloc_agp_mem(struct fb_info *info) struct i810fb_par *par = info->par; int size; struct agp_bridge_data *bridge; - + i810_fix_offsets(par); size = par->fb.size + par->iring.size; @@ -1674,7 +1674,7 @@ static int i810_alloc_agp_mem(struct fb_info *info) printk("i810fb_alloc_fbmem: cannot acquire agpgart\n"); return -ENODEV; } - if (!(par->i810_gtt.i810_fb_memory = + if (!(par->i810_gtt.i810_fb_memory = agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) { printk("i810fb_alloc_fbmem: can't allocate framebuffer " "memory\n"); @@ -1686,9 +1686,9 @@ static int i810_alloc_agp_mem(struct fb_info *info) printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n"); agp_backend_release(bridge); return -EBUSY; - } - - if (!(par->i810_gtt.i810_cursor_memory = + } + + if (!(par->i810_gtt.i810_cursor_memory = agp_allocate_memory(bridge, par->cursor_heap.size >> 12, AGP_PHYSICAL_MEMORY))) { printk("i810fb_alloc_cursormem: can't allocate " @@ -1701,7 +1701,7 @@ static int i810_alloc_agp_mem(struct fb_info *info) printk("i810fb_alloc_cursormem: cannot bind cursor memory\n"); agp_backend_release(bridge); return -EBUSY; - } + } par->cursor_heap.physical = par->i810_gtt.i810_cursor_memory->physical; @@ -1712,8 +1712,8 @@ static int i810_alloc_agp_mem(struct fb_info *info) return 0; } -/*************************************************************** - * Initialization * +/*************************************************************** + * Initialization * ***************************************************************/ /** @@ -1728,7 +1728,7 @@ static void i810_init_monspecs(struct fb_info *info) { if (!hsync1) hsync1 = HFMIN; - if (!hsync2) + if (!hsync2) hsync2 = HFMAX; if (!info->monspecs.hfmax) info->monspecs.hfmax = hsync2; @@ -1739,7 +1739,7 @@ static void i810_init_monspecs(struct fb_info *info) if (!vsync1) vsync1 = VFMIN; - if (!vsync2) + if (!vsync2) vsync2 = VFMAX; if (IS_DVT && vsync1 < 60) vsync1 = 60; @@ -1747,7 +1747,7 @@ static void i810_init_monspecs(struct fb_info *info) info->monspecs.vfmax = vsync2; if (!info->monspecs.vfmin) info->monspecs.vfmin = vsync1; - if (vsync2 < vsync1) + if (vsync2 < vsync1) info->monspecs.vfmin = vsync2; } @@ -1760,27 +1760,27 @@ static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info) { mutex_init(&par->open_lock); - if (voffset) + if (voffset) v_offset_default = voffset; else if (par->aperture.size > 32 * 1024 * 1024) v_offset_default = 16; else v_offset_default = 8; - if (!vram) + if (!vram) vram = 1; - if (accel) + if (accel) par->dev_flags |= HAS_ACCELERATION; - if (sync) + if (sync) par->dev_flags |= ALWAYS_SYNC; par->ddc_num = (ddc3 ? 3 : 2); if (bpp < 8) bpp = 8; - + par->i810fb_ops = i810fb_ops; if (xres) @@ -1793,7 +1793,7 @@ static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info) else info->var.yres = 480; - if (!vyres) + if (!vyres) vyres = (vram << 20)/(info->var.xres*bpp >> 3); info->var.yres_virtual = vyres; @@ -1802,12 +1802,12 @@ static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info) if (dcolor) info->var.nonstd = 1; - if (par->dev_flags & HAS_ACCELERATION) + if (par->dev_flags & HAS_ACCELERATION) info->var.accel_flags = 1; i810_init_monspecs(info); } - + /** * i810_init_device - initialize device * @par: pointer to i810fb_par structure @@ -1840,9 +1840,9 @@ static int i810_allocate_pci_resource(struct i810fb_par *par, { int err; - if ((err = pci_enable_device(par->dev))) { + if ((err = pci_enable_device(par->dev))) { printk("i810fb_init: cannot enable device\n"); - return err; + return err; } par->res_flags |= PCI_DEVICE_ENABLED; @@ -1860,8 +1860,8 @@ static int i810_allocate_pci_resource(struct i810fb_par *par, return -ENOMEM; } - if (!request_mem_region(par->aperture.physical, - par->aperture.size, + if (!request_mem_region(par->aperture.physical, + par->aperture.size, i810_pci_list[entry->driver_data])) { printk("i810fb_init: cannot request framebuffer region\n"); return -ENODEV; @@ -1874,16 +1874,16 @@ static int i810_allocate_pci_resource(struct i810fb_par *par, printk("i810fb_init: cannot remap framebuffer region\n"); return -ENODEV; } - - if (!request_mem_region(par->mmio_start_phys, - MMIO_SIZE, + + if (!request_mem_region(par->mmio_start_phys, + MMIO_SIZE, i810_pci_list[entry->driver_data])) { printk("i810fb_init: cannot request mmio region\n"); return -ENODEV; } par->res_flags |= MMIO_REQ; - par->mmio_start_virtual = ioremap(par->mmio_start_phys, + par->mmio_start_virtual = ioremap(par->mmio_start_phys, MMIO_SIZE); if (!par->mmio_start_virtual) { printk("i810fb_init: cannot remap mmio region\n"); @@ -1963,7 +1963,7 @@ static int i810fb_setup(char *options) if (!options || !*options) return 0; - + while ((this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "mtrr", 4)) mtrr = true; @@ -1987,13 +1987,13 @@ static int i810fb_setup(char *options) bpp = simple_strtoul(this_opt+4, NULL, 0); else if (!strncmp(this_opt, "hsync1:", 7)) { hsync1 = simple_strtoul(this_opt+7, &suffix, 0); - if (strncmp(suffix, "H", 1)) + if (strncmp(suffix, "H", 1)) hsync1 *= 1000; } else if (!strncmp(this_opt, "hsync2:", 7)) { hsync2 = simple_strtoul(this_opt+7, &suffix, 0); - if (strncmp(suffix, "H", 1)) + if (strncmp(suffix, "H", 1)) hsync2 *= 1000; - } else if (!strncmp(this_opt, "vsync1:", 7)) + } else if (!strncmp(this_opt, "vsync1:", 7)) vsync1 = simple_strtoul(this_opt+7, NULL, 0); else if (!strncmp(this_opt, "vsync2:", 7)) vsync2 = simple_strtoul(this_opt+7, NULL, 0); @@ -2044,7 +2044,7 @@ static int i810fb_init_pci(struct pci_dev *dev, return err; } - i810_init_device(par); + i810_init_device(par); info->screen_base = par->fb.virtual; info->fbops = &par->i810fb_ops; @@ -2064,21 +2064,21 @@ static int i810fb_init_pci(struct pci_dev *dev, err = register_framebuffer(info); if (err < 0) { - i810fb_release_resource(info, par); + i810fb_release_resource(info, par); printk("i810fb_init: cannot register framebuffer device\n"); - return err; - } + return err; + } pci_set_drvdata(dev, info); pixclock = 1000000000/(info->var.pixclock); pixclock *= 1000; - hfreq = pixclock/(info->var.xres + info->var.left_margin + + hfreq = pixclock/(info->var.xres + info->var.left_margin + info->var.hsync_len + info->var.right_margin); vfreq = hfreq/(info->var.yres + info->var.upper_margin + info->var.vsync_len + info->var.lower_margin); printk("I810FB: fb%d : %s v%d.%d.%d%s\n" - "I810FB: Video RAM : %dK\n" + "I810FB: Video RAM : %dK\n" "I810FB: Monitor : H: %d-%d KHz V: %d-%d Hz\n" "I810FB: Mode : %dx%d-%dbpp@%dHz\n", info->node, @@ -2086,7 +2086,7 @@ static int i810fb_init_pci(struct pci_dev *dev, VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION, (int) par->fb.size>>10, info->monspecs.hfmin/1000, info->monspecs.hfmax/1000, info->monspecs.vfmin, - info->monspecs.vfmax, info->var.xres, + info->monspecs.vfmax, info->var.xres, info->var.yres, info->var.bits_per_pixel, vfreq); return 0; } @@ -2095,7 +2095,7 @@ static int i810fb_init_pci(struct pci_dev *dev, * De-initialization * ***************************************************************/ -static void i810fb_release_resource(struct fb_info *info, +static void i810fb_release_resource(struct fb_info *info, struct i810fb_par *par) { struct gtt_data *gtt = &par->i810_gtt; @@ -2128,10 +2128,10 @@ static void i810fb_remove_pci(struct pci_dev *dev) struct fb_info *info = pci_get_drvdata(dev); struct i810fb_par *par = info->par; - unregister_framebuffer(info); + unregister_framebuffer(info); i810fb_release_resource(info, par); printk("cleanup_module: unloaded i810 framebuffer device\n"); -} +} #ifndef MODULE static int i810fb_init(void) @@ -2144,7 +2144,7 @@ static int i810fb_init(void) return pci_register_driver(&i810fb_driver); } -#endif +#endif /********************************************************************* * Modularization * @@ -2161,7 +2161,7 @@ static int i810fb_init(void) } module_param(vram, int, 0); -MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB" +MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB" " (default=4)"); module_param(voffset, int, 0); MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer " @@ -2186,7 +2186,7 @@ module_param(vsync1, int, 0); MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz" " (default = 50)"); module_param(vsync2, int, 0); -MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz" +MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz" " (default = 60)"); module_param(accel, bool, 0); MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)"); @@ -2208,7 +2208,7 @@ MODULE_PARM_DESC(mode_option, "Specify initial video mode"); MODULE_AUTHOR("Tony A. Daplas"); MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and" " compatible cards"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL"); static void __exit i810fb_exit(void) { diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index 16f272a50811..f489386855c0 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -86,7 +86,7 @@ enum { SSTATUS = 36, /* 0x90 */ PRC = 37, /* 0x94 */ -#if 0 +#if 0 /* PCI Registers */ DVID = 0x00000000L, SC = 0x00000004L, @@ -103,8 +103,8 @@ enum { PDATA = 0x04, PPMASK = 0x08, PADDRR = 0x0c, - PIDXLO = 0x10, - PIDXHI = 0x14, + PIDXLO = 0x10, + PIDXHI = 0x14, PIDXDATA= 0x18, PIDXCTL = 0x1c }; @@ -131,7 +131,7 @@ enum { SYSCLKC = 0x18, /* () System Clock C */ /* * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1) - * c is charge pump bias which depends on the VCO frequency + * c is charge pump bias which depends on the VCO frequency */ PIXM0 = 0x20, /* () Pixel M 0 */ PIXN0 = 0x21, /* () Pixel N 0 */ @@ -320,7 +320,7 @@ struct imstt_par { __u32 ramdac; __u32 palette[16]; }; - + enum { IBM = 0, TVP = 1 @@ -373,7 +373,7 @@ static struct imstt_regvals tvp_reg_init_17 = { static struct imstt_regvals tvp_reg_init_18 = { 1152, - 0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, + 0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 0xfd, 0x3a, 0xf1, { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 } }; @@ -856,10 +856,10 @@ imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) } static int -imsttfb_set_par(struct fb_info *info) +imsttfb_set_par(struct fb_info *info) { struct imstt_par *par = info->par; - + if (!compute_imstt_regvals(par, info->var.xres, info->var.yres)) return -EINVAL; @@ -930,7 +930,7 @@ imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) return 0; } -static int +static int imsttfb_blank(int blank, struct fb_info *info) { struct imstt_par *par = info->par; @@ -986,7 +986,7 @@ imsttfb_blank(int blank, struct fb_info *info) static void imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -{ +{ struct imstt_par *par = info->par; __u32 Bpp, line_pitch, bgc, dx, dy, width, height; @@ -1192,7 +1192,7 @@ imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on) } } -static int +static int imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct imstt_par *par = info->par; @@ -1200,7 +1200,7 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor) if (cursor->dest == NULL && cursor->rop == ROP_XOR) return 1; - + imstt_set_cursor(info, cursor, 0); if (flags & FB_CUR_SETPOS) { @@ -1470,7 +1470,7 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct fb_info *info; struct device_node *dp; int ret = -ENOMEM; - + dp = pci_device_to_OF_node(pdev); if(dp) printk(KERN_INFO "%s: OF name %pOFn\n",__func__, dp); @@ -1619,7 +1619,7 @@ static int __init imsttfb_init(void) #endif return pci_register_driver(&imsttfb_pci_driver); } - + static void __exit imsttfb_exit(void) { pci_unregister_driver(&imsttfb_pci_driver); diff --git a/drivers/video/fbdev/neofb.c b/drivers/video/fbdev/neofb.c index 28d32cbf496b..8ad2a79623af 100644 --- a/drivers/video/fbdev/neofb.c +++ b/drivers/video/fbdev/neofb.c @@ -23,9 +23,9 @@ * * 0.3.3 * - Porting over to new fbdev api. (jsimmons) - * + * * 0.3.2 - * - got rid of all floating point (dok) + * - got rid of all floating point (dok) * * 0.3.1 * - added module license (dok) @@ -1154,14 +1154,14 @@ static int neofb_set_par(struct fb_info *info) switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: - case FB_ACCEL_NEOMAGIC_NM2230: - case FB_ACCEL_NEOMAGIC_NM2360: - case FB_ACCEL_NEOMAGIC_NM2380: + case FB_ACCEL_NEOMAGIC_NM2230: + case FB_ACCEL_NEOMAGIC_NM2360: + case FB_ACCEL_NEOMAGIC_NM2380: neo2200_accel_init(info, &info->var); break; default: break; - } + } return 0; } @@ -1493,15 +1493,15 @@ neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: - case FB_ACCEL_NEOMAGIC_NM2230: - case FB_ACCEL_NEOMAGIC_NM2360: + case FB_ACCEL_NEOMAGIC_NM2230: + case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: neo2200_fillrect(info, rect); break; default: cfb_fillrect(info, rect); break; - } + } } static void @@ -1509,15 +1509,15 @@ neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: - case FB_ACCEL_NEOMAGIC_NM2230: - case FB_ACCEL_NEOMAGIC_NM2360: - case FB_ACCEL_NEOMAGIC_NM2380: + case FB_ACCEL_NEOMAGIC_NM2230: + case FB_ACCEL_NEOMAGIC_NM2360: + case FB_ACCEL_NEOMAGIC_NM2380: neo2200_copyarea(info, area); break; default: cfb_copyarea(info, area); break; - } + } } static void @@ -1536,20 +1536,20 @@ neofb_imageblit(struct fb_info *info, const struct fb_image *image) } } -static int +static int neofb_sync(struct fb_info *info) { switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: - case FB_ACCEL_NEOMAGIC_NM2230: - case FB_ACCEL_NEOMAGIC_NM2360: - case FB_ACCEL_NEOMAGIC_NM2380: + case FB_ACCEL_NEOMAGIC_NM2230: + case FB_ACCEL_NEOMAGIC_NM2360: + case FB_ACCEL_NEOMAGIC_NM2380: neo2200_sync(info); break; default: break; } - return 0; + return 0; } /* diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index 84d5e23ad7d3..5bafc44c591b 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -474,7 +474,7 @@ static inline void reverse_order(u32 *l) * DESCRIPTiON: * Loads cursor image based on a monochrome source and mask bitmap. The * image bits determines the color of the pixel, 0 for background, 1 for - * foreground. Only the affected region (as determined by @w and @h + * foreground. Only the affected region (as determined by @w and @h * parameters) will be updated. * * CALLED FROM: @@ -494,7 +494,7 @@ static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8, for (i = 0; i < h; i++) { b = *data++; reverse_order(&b); - + for (j = 0; j < w/2; j++) { tmp = 0; #if defined (__BIG_ENDIAN) @@ -562,7 +562,7 @@ static void riva_rclut(RIVA_HW_INST *chip, unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue) { - + VGA_WR08(chip->PDIO, 0x3c7, regnum); *red = VGA_RD08(chip->PDIO, 0x3c9); *green = VGA_RD08(chip->PDIO, 0x3c9); @@ -673,7 +673,7 @@ static int riva_load_video_mode(struct fb_info *info) int rc; struct riva_par *par = info->par; struct riva_regs newmode; - + NVTRACE_ENTER(); /* time to calculate */ rivafb_blank(FB_BLANK_NORMAL, info); @@ -717,7 +717,7 @@ static int riva_load_video_mode(struct fb_info *info) hBlankEnd = hTotal + 4; } - newmode.crtc[0x0] = Set8Bits (hTotal); + newmode.crtc[0x0] = Set8Bits (hTotal); newmode.crtc[0x1] = Set8Bits (hDisplay); newmode.crtc[0x2] = Set8Bits (hBlankStart); newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7); @@ -748,20 +748,20 @@ static int riva_load_video_mode(struct fb_info *info) | SetBitField(vStart,10:10,2:2) | SetBitField(vDisplay,10:10,1:1) | SetBitField(vTotal,10:10,0:0); - newmode.ext.horiz = SetBitField(hTotal,8:8,0:0) + newmode.ext.horiz = SetBitField(hTotal,8:8,0:0) | SetBitField(hDisplay,8:8,1:1) | SetBitField(hBlankStart,8:8,2:2) | SetBitField(hStart,8:8,3:3); newmode.ext.extra = SetBitField(vTotal,11:11,0:0) | SetBitField(vDisplay,11:11,2:2) | SetBitField(vStart,11:11,4:4) - | SetBitField(vBlankStart,11:11,6:6); + | SetBitField(vBlankStart,11:11,6:6); if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { int tmp = (hTotal >> 1) & ~1; newmode.ext.interlace = Set8Bits(tmp); newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4); - } else + } else newmode.ext.interlace = 0xff; /* interlace off */ if (par->riva.Architecture >= NV_ARCH_10) @@ -774,7 +774,7 @@ static int riva_load_video_mode(struct fb_info *info) if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) newmode.misc_output &= ~0x80; else - newmode.misc_output |= 0x80; + newmode.misc_output |= 0x80; rc = CalcStateExt(&par->riva, &newmode.ext, par->pdev, bpp, width, hDisplaySize, height, dotClock); @@ -841,7 +841,7 @@ static void riva_update_var(struct fb_var_screeninfo *var, } /** - * rivafb_do_maximize - + * rivafb_do_maximize - * @info: pointer to fb_info object containing info for current riva board * @var: standard kernel fb changeable data * @nom: nom @@ -852,7 +852,7 @@ static void riva_update_var(struct fb_var_screeninfo *var, * * RETURNS: * -EINVAL on failure, 0 on success - * + * * * CALLED FROM: * rivafb_check_var() @@ -916,14 +916,14 @@ static int rivafb_do_maximize(struct fb_info *info, return -EINVAL; } } - + if (var->xres_virtual * nom / den >= 8192) { printk(KERN_WARNING PFX "virtual X resolution (%d) is too high, lowering to %d\n", var->xres_virtual, 8192 * den / nom - 16); var->xres_virtual = 8192 * den / nom - 16; } - + if (var->xres_virtual < var->xres) { printk(KERN_ERR PFX "virtual X resolution (%d) is smaller than real\n", var->xres_virtual); @@ -1010,7 +1010,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) break; case 6: rc = 64; /* 64 entries (2^6), 16 bpp, RGB565 */ - break; + break; default: /* should not occur */ break; @@ -1042,7 +1042,7 @@ static int rivafb_open(struct fb_info *info, int user) /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); par->riva.LockUnlock(&par->riva, 0); - + riva_save_state(par, &par->initial_state); } par->ref_count++; @@ -1082,7 +1082,7 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) struct riva_par *par = info->par; int nom, den; /* translating from pixels->bytes */ int mode_valid = 0; - + NVTRACE_ENTER(); if (!var->pixclock) return -EINVAL; @@ -1176,7 +1176,7 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (var->yoffset > var->yres_virtual - var->yres) var->yoffset = var->yres_virtual - var->yres - 1; - var->red.msb_right = + var->red.msb_right = var->green.msb_right = var->blue.msb_right = var->transp.offset = var->transp.length = var->transp.msb_right = 0; @@ -1198,7 +1198,7 @@ static int rivafb_set_par(struct fb_info *info) goto out; if(!(info->flags & FBINFO_HWACCEL_DISABLED)) riva_setup_accel(info); - + par->cursor_reset = 1; info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3)); info->fix.visual = (info->var.bits_per_pixel == 8) ? @@ -1486,7 +1486,7 @@ static inline void convert_bgcolor_16(u32 *col) * CALLED FROM: * framebuffer hook */ -static void rivafb_imageblit(struct fb_info *info, +static void rivafb_imageblit(struct fb_info *info, const struct fb_image *image) { struct riva_par *par = info->par; @@ -1515,7 +1515,7 @@ static void rivafb_imageblit(struct fb_info *info, bgx = par->palette[image->bg_color]; } if (info->var.green.length == 6) - convert_bgcolor_16(&bgx); + convert_bgcolor_16(&bgx); break; } @@ -1612,7 +1612,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) u8 *dat = (u8 *) cursor->image.data; u8 *msk = (u8 *) cursor->mask; u8 *src; - + src = kmalloc_array(s_pitch, cursor->image.height, GFP_ATOMIC); if (src) { @@ -1683,7 +1683,7 @@ static const struct fb_ops riva_fb_ops = { .fb_fillrect = rivafb_fillrect, .fb_copyarea = rivafb_copyarea, .fb_imageblit = rivafb_imageblit, - .fb_cursor = rivafb_cursor, + .fb_cursor = rivafb_cursor, .fb_sync = rivafb_sync, }; @@ -1713,7 +1713,7 @@ static int riva_set_fbinfo(struct fb_info *info) info->pseudo_palette = par->pseudo_palette; cmap_len = riva_get_cmap_len(&info->var); - fb_alloc_cmap(&info->cmap, cmap_len, 0); + fb_alloc_cmap(&info->cmap, cmap_len, 0); info->pixmap.size = 8 * 1024; info->pixmap.buf_align = 4; @@ -1929,7 +1929,7 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent) default_par->Chipset = (pd->vendor << 16) | pd->device; printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset); - + if(default_par->riva.Architecture == 0) { printk(KERN_ERR PFX "unknown NV_ARCH\n"); ret=-ENODEV; @@ -1947,7 +1947,7 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent) if (flatpanel == 1) printk(KERN_INFO PFX "flatpanel support enabled\n"); default_par->forceCRTC = forceCRTC; - + rivafb_fix.mmio_len = pci_resource_len(pd, 0); rivafb_fix.smem_len = pci_resource_len(pd, 1); @@ -1959,7 +1959,7 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent) cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); pci_write_config_word(pd, PCI_COMMAND, cmd); } - + rivafb_fix.mmio_start = pci_resource_start(pd, 0); rivafb_fix.smem_start = pci_resource_start(pd, 1); @@ -2058,7 +2058,7 @@ err_iounmap_screen_base: #endif iounmap(info->screen_base); err_iounmap_pramin: - if (default_par->riva.Architecture == NV_ARCH_03) + if (default_par->riva.Architecture == NV_ARCH_03) iounmap(default_par->riva.PRAMIN); err_iounmap_ctrl_base: iounmap(default_par->ctrl_base); @@ -2077,7 +2077,7 @@ static void rivafb_remove(struct pci_dev *pd) { struct fb_info *info = pci_get_drvdata(pd); struct riva_par *par = info->par; - + NVTRACE_ENTER(); #ifdef CONFIG_FB_RIVA_I2C @@ -2117,11 +2117,11 @@ static int rivafb_setup(char *options) while ((this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "forceCRTC", 9)) { char *p; - + p = this_opt + 9; - if (!*p || !*(++p)) continue; + if (!*p || !*(++p)) continue; forceCRTC = *p - '0'; - if (forceCRTC < 0 || forceCRTC > 1) + if (forceCRTC < 0 || forceCRTC > 1) forceCRTC = -1; } else if (!strncmp(this_opt, "flatpanel", 9)) { flatpanel = 1; diff --git a/drivers/video/fbdev/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c index d119b1d08007..304320ce6c6f 100644 --- a/drivers/video/fbdev/skeletonfb.c +++ b/drivers/video/fbdev/skeletonfb.c @@ -10,32 +10,32 @@ * The primary goal is to remove the console code from fbdev and place it * into fbcon.c. This reduces the code and makes writing a new fbdev driver * easy since the author doesn't need to worry about console internals. It - * also allows the ability to run fbdev without a console/tty system on top - * of it. + * also allows the ability to run fbdev without a console/tty system on top + * of it. * * First the roles of struct fb_info and struct display have changed. Struct * display will go away. The way the new framebuffer console code will - * work is that it will act to translate data about the tty/console in + * work is that it will act to translate data about the tty/console in * struct vc_data to data in a device independent way in struct fb_info. Then - * various functions in struct fb_ops will be called to store the device - * dependent state in the par field in struct fb_info and to change the + * various functions in struct fb_ops will be called to store the device + * dependent state in the par field in struct fb_info and to change the * hardware to that state. This allows a very clean separation of the fbdev * layer from the console layer. It also allows one to use fbdev on its own - * which is a bounus for embedded devices. The reason this approach works is + * which is a bounus for embedded devices. The reason this approach works is * for each framebuffer device when used as a tty/console device is allocated - * a set of virtual terminals to it. Only one virtual terminal can be active - * per framebuffer device. We already have all the data we need in struct + * a set of virtual terminals to it. Only one virtual terminal can be active + * per framebuffer device. We already have all the data we need in struct * vc_data so why store a bunch of colormaps and other fbdev specific data - * per virtual terminal. + * per virtual terminal. * * As you can see doing this makes the con parameter pretty much useless - * for struct fb_ops functions, as it should be. Also having struct - * fb_var_screeninfo and other data in fb_info pretty much eliminates the + * for struct fb_ops functions, as it should be. Also having struct + * fb_var_screeninfo and other data in fb_info pretty much eliminates the * need for get_fix and get_var. Once all drivers use the fix, var, and cmap * fbcon can be written around these fields. This will also eliminate the * need to regenerate struct fb_var_screeninfo, struct fb_fix_screeninfo * struct fb_cmap every time get_var, get_fix, get_cmap functions are called - * as many drivers do now. + * as many drivers do now. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -66,68 +66,68 @@ static char *mode_option; /* - * If your driver supports multiple boards, you should make the - * below data types arrays, or allocate them dynamically (using kmalloc()). - */ + * If your driver supports multiple boards, you should make the + * below data types arrays, or allocate them dynamically (using kmalloc()). + */ -/* +/* * This structure defines the hardware state of the graphics card. Normally * you place this in a header file in linux/include/video. This file usually * also includes register information. That allows other driver subsystems - * and userland applications the ability to use the same header file to - * avoid duplicate work and easy porting of software. + * and userland applications the ability to use the same header file to + * avoid duplicate work and easy porting of software. */ struct xxx_par; /* * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo * if we don't use modedb. If we do use modedb see xxxfb_init how to use it - * to get a fb_var_screeninfo. Otherwise define a default var as well. + * to get a fb_var_screeninfo. Otherwise define a default var as well. */ static const struct fb_fix_screeninfo xxxfb_fix = { - .id = "FB's name", + .id = "FB's name", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_PSEUDOCOLOR, .xpanstep = 1, .ypanstep = 1, - .ywrapstep = 1, + .ywrapstep = 1, .accel = FB_ACCEL_NONE, }; /* - * Modern graphical hardware not only supports pipelines but some + * Modern graphical hardware not only supports pipelines but some * also support multiple monitors where each display can have - * its own unique data. In this case each display could be - * represented by a separate framebuffer device thus a separate + * its own unique data. In this case each display could be + * represented by a separate framebuffer device thus a separate * struct fb_info. Now the struct xxx_par represents the graphics - * hardware state thus only one exist per card. In this case the - * struct xxx_par for each graphics card would be shared between - * every struct fb_info that represents a framebuffer on that card. - * This allows when one display changes it video resolution (info->var) + * hardware state thus only one exist per card. In this case the + * struct xxx_par for each graphics card would be shared between + * every struct fb_info that represents a framebuffer on that card. + * This allows when one display changes it video resolution (info->var) * the other displays know instantly. Each display can always be * aware of the entire hardware state that affects it because they share * the same xxx_par struct. The other side of the coin is multiple * graphics cards that pass data around until it is finally displayed * on one monitor. Such examples are the voodoo 1 cards and high end * NUMA graphics servers. For this case we have a bunch of pars, each - * one that represents a graphics state, that belong to one struct + * one that represents a graphics state, that belong to one struct * fb_info. Their you would want to have *par point to a array of device - * states and have each struct fb_ops function deal with all those + * states and have each struct fb_ops function deal with all those * states. I hope this covers every possible hardware design. If not - * feel free to send your ideas at jsimmons@users.sf.net + * feel free to send your ideas at jsimmons@users.sf.net */ /* - * If your driver supports multiple boards or it supports multiple - * framebuffers, you should make these arrays, or allocate them + * If your driver supports multiple boards or it supports multiple + * framebuffers, you should make these arrays, or allocate them * dynamically using framebuffer_alloc() and free them with * framebuffer_release(). - */ + */ static struct fb_info info; - /* + /* * Each one represents the state of the hardware. Most hardware have - * just one hardware state. These here represent the default state(s). + * just one hardware state. These here represent the default state(s). */ static struct xxx_par __initdata current_par; @@ -138,12 +138,12 @@ int xxxfb_init(void); * first accessed. * @info: frame buffer structure that represents a single frame buffer * @user: tell us if the userland (value=1) or the console is accessing - * the framebuffer. + * the framebuffer. * * This function is the first function called in the framebuffer api. - * Usually you don't need to provide this function. The case where it + * Usually you don't need to provide this function. The case where it * is used is to change from a text mode hardware state to a graphics - * mode state. + * mode state. * * Returns negative errno on error, or zero on success. */ @@ -153,13 +153,13 @@ static int xxxfb_open(struct fb_info *info, int user) } /** - * xxxfb_release - Optional function. Called when the framebuffer - * device is closed. + * xxxfb_release - Optional function. Called when the framebuffer + * device is closed. * @info: frame buffer structure that represents a single frame buffer * @user: tell us if the userland (value=1) or the console is accessing - * the framebuffer. - * - * Thus function is called when we close /dev/fb or the framebuffer + * the framebuffer. + * + * Thus function is called when we close /dev/fb or the framebuffer * console system is released. Usually you don't need this function. * The case where it is usually used is to go from a graphics state * to a text mode state. @@ -172,17 +172,17 @@ static int xxxfb_release(struct fb_info *info, int user) } /** - * xxxfb_check_var - Optional function. Validates a var passed in. + * xxxfb_check_var - Optional function. Validates a var passed in. * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer + * @info: frame buffer structure that represents a single frame buffer * * Checks to see if the hardware supports the state requested by - * var passed in. This function does not alter the hardware state!!! - * This means the data stored in struct fb_info and struct xxx_par do - * not change. This includes the var inside of struct fb_info. + * var passed in. This function does not alter the hardware state!!! + * This means the data stored in struct fb_info and struct xxx_par do + * not change. This includes the var inside of struct fb_info. * Do NOT change these. This function can be called on its own if we - * intent to only test a mode and not actually set it. The stuff in - * modedb.c is a example of this. If the var passed in is slightly + * intent to only test a mode and not actually set it. The stuff in + * modedb.c is a example of this. If the var passed in is slightly * off by what the hardware can support then we alter the var PASSED in * to what we can do. * @@ -210,7 +210,7 @@ static int xxxfb_release(struct fb_info *info, int user) static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { /* ... */ - return 0; + return 0; } /** @@ -219,9 +219,9 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) * * Using the fb_var_screeninfo in fb_info we set the resolution of the * this particular framebuffer. This function alters the par AND the - * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in + * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in * fb_info since we are using that data. This means we depend on the - * data in var inside fb_info to be supported by the hardware. + * data in var inside fb_info to be supported by the hardware. * * This function is also used to recover/restore the hardware to a * known working state. @@ -256,20 +256,20 @@ static int xxxfb_set_par(struct fb_info *info) { struct xxx_par *par = info->par; /* ... */ - return 0; + return 0; } /** * xxxfb_setcolreg - Optional function. Sets a color register. - * @regno: Which register in the CLUT we are programming - * @red: The red value which can be up to 16 bits wide - * @green: The green value which can be up to 16 bits wide + * @regno: Which register in the CLUT we are programming + * @red: The red value which can be up to 16 bits wide + * @green: The green value which can be up to 16 bits wide * @blue: The blue value which can be up to 16 bits wide. * @transp: If supported, the alpha value which can be up to 16 bits wide. * @info: frame buffer info structure - * + * * Set a single color register. The values supplied have a 16 bit - * magnitude which needs to be scaled in this function for the hardware. + * magnitude which needs to be scaled in this function for the hardware. * Things to take into consideration are how many color registers, if * any, are supported with the current color visual. With truecolor mode * no color palettes are supported. Here a pseudo palette is created @@ -277,8 +277,8 @@ static int xxxfb_set_par(struct fb_info *info) * pseudocolor mode we have a limited color palette. To deal with this * we can program what color is displayed for a particular pixel value. * DirectColor is similar in that we can program each color field. If - * we have a static colormap we don't need to implement this function. - * + * we have a static colormap we don't need to implement this function. + * * Returns negative errno on error, or zero on success. */ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -442,7 +442,7 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var, /** * xxxfb_blank - NOT a required function. Blanks the display. - * @blank_mode: the blank mode we want. + * @blank_mode: the blank mode we want. * @info: frame buffer structure that represents a single frame buffer * * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank. @@ -471,22 +471,22 @@ static int xxxfb_blank(int blank_mode, struct fb_info *info) /* * We provide our own functions if we have hardware acceleration - * or non packed pixel format layouts. If we have no hardware + * or non packed pixel format layouts. If we have no hardware * acceleration, we can use a generic unaccelerated function. If using - * a pack pixel format just use the functions in cfb_*.c. Each file + * a pack pixel format just use the functions in cfb_*.c. Each file * has one of the three different accel functions we support. */ /** - * xxxfb_fillrect - REQUIRED function. Can use generic routines if + * xxxfb_fillrect - REQUIRED function. Can use generic routines if * non acclerated hardware and packed pixel based. - * Draws a rectangle on the screen. + * Draws a rectangle on the screen. * * @info: frame buffer structure that represents a single frame buffer - * @region: The structure representing the rectangular region we + * @region: The structure representing the rectangular region we * wish to draw to. * - * This drawing operation places/removes a retangle on the screen + * This drawing operation places/removes a retangle on the screen * depending on the rastering operation with the value of color which * is in the current color depth format. */ @@ -494,13 +494,13 @@ void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region) { /* Meaning of struct fb_fillrect * - * @dx: The x and y corrdinates of the upper left hand corner of the - * @dy: area we want to draw to. + * @dx: The x and y corrdinates of the upper left hand corner of the + * @dy: area we want to draw to. * @width: How wide the rectangle is we want to draw. * @height: How tall the rectangle is we want to draw. - * @color: The color to fill in the rectangle with. + * @color: The color to fill in the rectangle with. * @rop: The raster operation. We can draw the rectangle with a COPY - * of XOR which provides erasing effect. + * of XOR which provides erasing effect. */ } @@ -516,7 +516,7 @@ void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region) * This drawing operation copies a rectangular area from one area of the * screen to another area. */ -void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) +void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) { /* * @dx: The x and y coordinates of the upper left hand corner of the @@ -532,28 +532,28 @@ void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) /** * xxxfb_imageblit - REQUIRED function. Can use generic routines if * non acclerated hardware and packed pixel based. - * Copies a image from system memory to the screen. + * Copies a image from system memory to the screen. * * @info: frame buffer structure that represents a single frame buffer * @image: structure defining the image. * - * This drawing operation draws a image on the screen. It can be a + * This drawing operation draws a image on the screen. It can be a * mono image (needed for font handling) or a color image (needed for - * tux). + * tux). */ -void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) +void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) { /* * @dx: The x and y coordinates of the upper left hand corner of the * @dy: destination area to place the image on the screen. * @width: How wide the image is we want to copy. * @height: How tall the image is we want to copy. - * @fg_color: For mono bitmap images this is color data for + * @fg_color: For mono bitmap images this is color data for * @bg_color: the foreground and background of the image to * write directly to the frmaebuffer. * @depth: How many bits represent a single pixel for this image. * @data: The actual data used to construct the image on the display. - * @cmap: The colormap used for color images. + * @cmap: The colormap used for color images. */ /* @@ -580,13 +580,13 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) { /* - * @set: Which fields we are altering in struct fb_cursor - * @enable: Disable or enable the cursor - * @rop: The bit operation we want to do. - * @mask: This is the cursor mask bitmap. + * @set: Which fields we are altering in struct fb_cursor + * @enable: Disable or enable the cursor + * @rop: The bit operation we want to do. + * @mask: This is the cursor mask bitmap. * @dest: A image of the area we are going to display the cursor. - * Used internally by the driver. - * @hot: The hot spot. + * Used internally by the driver. + * @hot: The hot spot. * @image: The actual data for the cursor image. * * NOTES ON FLAGS (cursor->set): @@ -614,11 +614,11 @@ int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) } /** - * xxxfb_sync - NOT a required function. Normally the accel engine + * xxxfb_sync - NOT a required function. Normally the accel engine * for a graphics card take a specific amount of time. * Often we have to wait for the accelerator to finish * its operation before we can write to the framebuffer - * so we can have consistent display output. + * so we can have consistent display output. * * @info: frame buffer structure that represents a single frame buffer * @@ -666,8 +666,8 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent) struct fb_info *info; struct xxx_par *par; struct device *device = &dev->dev; /* or &pdev->dev */ - int cmap_len, retval; - + int cmap_len, retval; + /* * Dynamically allocate info and par */ @@ -679,11 +679,11 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent) par = info->par; - /* + /* * Here we set the screen_base to the virtual memory address * for the framebuffer. Usually we obtain the resource address * from the bus layer and then translate it to virtual memory - * space via ioremap. Consult ioport.h. + * space via ioremap. Consult ioport.h. */ info->screen_base = framebuffer_virtual_memory; info->fbops = &xxxfb_ops; @@ -767,24 +767,24 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent) /* * This should give a reasonable default video mode. The following is - * done when we can set a video mode. + * done when we can set a video mode. */ if (!mode_option) - mode_option = "640x480@60"; + mode_option = "640x480@60"; retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); - + if (!retval || retval == 4) - return -EINVAL; + return -EINVAL; /* This has to be done! */ if (fb_alloc_cmap(&info->cmap, cmap_len, 0)) return -ENOMEM; - - /* - * The following is done in the case of having hardware with a static - * mode. If we are setting the mode ourselves we don't call this. - */ + + /* + * The following is done in the case of having hardware with a static + * mode. If we are setting the mode ourselves we don't call this. + */ info->var = xxxfb_var; /* diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c index 27d4b0ace2d6..535ef4693cd4 100644 --- a/drivers/video/fbdev/sstfb.c +++ b/drivers/video/fbdev/sstfb.c @@ -364,7 +364,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, return -EINVAL; } var->pixclock = KHZ2PICOS(freq); - + if (var->vmode & FB_VMODE_INTERLACED) vBackPorch += (vBackPorch % 2); if (var->vmode & FB_VMODE_DOUBLE) { @@ -382,7 +382,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel); return -EINVAL; } - + /* validity tests */ if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1 || hSyncOff <= 1 || var->left_margin <= 2 || vSyncOn <= 0 || @@ -392,7 +392,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, if (IS_VOODOO2(par)) { /* Voodoo 2 limits */ - tiles_in_X = (var->xres + 63 ) / 64 * 2; + tiles_in_X = (var->xres + 63 ) / 64 * 2; if (var->xres > POW2(11) || yDim >= POW2(11)) { printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n", @@ -631,7 +631,7 @@ static int sstfb_set_par(struct fb_info *info) lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR | LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD ); #endif - + if (clipping) { sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE); /* @@ -684,7 +684,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | (green << info->var.green.offset) | (blue << info->var.blue.offset) | (transp << info->var.transp.offset); - + par->palette[regno] = col; return 0; @@ -773,7 +773,7 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { struct sstfb_par *par = info->par; u32 stride = info->fix.line_length; - + if (!IS_VOODOO2(par)) return; @@ -795,17 +795,17 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only */ #if 0 -static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct sstfb_par *par = info->par; u32 stride = info->fix.line_length; if (!IS_VOODOO2(par)) return; - + sst_write(BLTCLIPX, info->var.xres); sst_write(BLTCLIPY, info->var.yres); - + sst_write(BLTDSTBASEADDR, 0); sst_write(BLTCOLOR, rect->color); sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR); @@ -820,8 +820,8 @@ static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -/* - * get lfb size +/* + * get lfb size */ static int sst_get_memsize(struct fb_info *info, __u32 *memsize) { @@ -859,8 +859,8 @@ static int sst_get_memsize(struct fb_info *info, __u32 *memsize) } -/* - * DAC detection routines +/* + * DAC detection routines */ /* fbi should be idle, and fifo emty and mem disabled */ @@ -963,7 +963,7 @@ static int sst_detect_ics(struct fb_info *info) * see detect_dac */ -static int sst_set_pll_att_ti(struct fb_info *info, +static int sst_set_pll_att_ti(struct fb_info *info, const struct pll_timing *t, const int clock) { struct sstfb_par *par = info->par; @@ -1338,10 +1338,10 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENOMEM; pci_set_drvdata(pdev, info); - + par = info->par; fix = &info->fix; - + par->type = id->driver_data; spec = &voodoo_spec[par->type]; f_ddprintk("found device : %s\n", spec->name); @@ -1407,7 +1407,7 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) * fact dithered to 16bit). */ fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */ - + fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16); if (sstfb_check_var(&info->var, info)) { @@ -1419,7 +1419,7 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_ERR "sstfb: can't set default video mode.\n"); goto fail; } - + if (fb_alloc_cmap(&info->cmap, 256, 0)) { printk(KERN_ERR "sstfb: can't alloc cmap memory.\n"); goto fail; @@ -1465,7 +1465,7 @@ static void sstfb_remove(struct pci_dev *pdev) info = pci_get_drvdata(pdev); par = info->par; - + device_remove_file(info->dev, &device_attrs[0]); sst_shutdown(info); iounmap(info->screen_base); diff --git a/drivers/video/fbdev/tgafb.c b/drivers/video/fbdev/tgafb.c index ae0cf5540636..9266c76783cc 100644 --- a/drivers/video/fbdev/tgafb.c +++ b/drivers/video/fbdev/tgafb.c @@ -729,7 +729,7 @@ tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image) /* Handle another common case in which accel_putcs generates a large bitmap, which happens to be aligned. - Allow the tail to be misaligned. This case is + Allow the tail to be misaligned. This case is interesting because we've not got to hold partial bytes across the words being written. */ @@ -908,9 +908,9 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) } /** - * tgafb_fillrect - REQUIRED function. Can use generic routines if + * tgafb_fillrect - REQUIRED function. Can use generic routines if * non acclerated hardware and packed pixel based. - * Draws a rectangle on the screen. + * Draws a rectangle on the screen. * * @info: frame buffer structure that represents a single frame buffer * @rect: structure defining the rectagle and operation. @@ -1044,7 +1044,7 @@ tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) /* Handle the special case of copying entire lines, e.g. during scrolling. We can avoid a lot of needless computation in this case. In the 8bpp - case we need to use the COPY64 registers instead of mask writes into + case we need to use the COPY64 registers instead of mask writes into the frame buffer to achieve maximum performance. */ static inline void @@ -1251,7 +1251,7 @@ copyarea_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy, } static void -tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { unsigned long dx, dy, width, height, sx, sy, vxres, vyres; unsigned long line_length, bpp; diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c index d21f68f3ee44..faf76972114d 100644 --- a/drivers/video/fbdev/vga16fb.c +++ b/drivers/video/fbdev/vga16fb.c @@ -1,13 +1,13 @@ /* * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver - * + * * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this - * archive for more details. + * archive for more details. */ #include <linux/module.h> @@ -70,7 +70,7 @@ static struct fb_var_screeninfo vga16fb_defined = { .yres = 480, .xres_virtual = 640, .yres_virtual = 480, - .bits_per_pixel = 4, + .bits_per_pixel = 4, .activate = FB_ACTIVATE_TEST, .height = -1, .width = -1, @@ -120,7 +120,7 @@ static inline void rmw(volatile char __iomem *p) static inline int setmode(int mode) { int oldmode; - + oldmode = vga_io_rgfx(VGA_GFX_MODE); vga_io_w(VGA_GFX_D, mode); return oldmode; @@ -139,19 +139,19 @@ static inline void setmask(int mask) vga_io_w(VGA_GFX_D, mask); } -/* Set the Data Rotate Register and return its old value. +/* Set the Data Rotate Register and return its old value. Bits 0-2 are rotate count, bits 3-4 are logical operation (0=NOP, 1=AND, 2=OR, 3=XOR). */ static inline int setop(int op) { int oldop; - + oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE); vga_io_w(VGA_GFX_D, op); return oldop; } -/* Set the Enable Set/Reset Register and return its old value. +/* Set the Enable Set/Reset Register and return its old value. The code here always uses value 0xf for this register. */ static inline int setsr(int sr) { @@ -203,7 +203,7 @@ static inline int check_mode_supported(void) return 0; } -static void vga16fb_pan_var(struct fb_info *info, +static void vga16fb_pan_var(struct fb_info *info, struct fb_var_screeninfo *var) { struct vga16fb_par *par = info->par; @@ -296,7 +296,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, par->clkdiv = best->seq_clock_mode; *pixclock = (best->pixclock * div) / mul; } - + #define FAIL(X) return -EINVAL static int vga16fb_open(struct fb_info *info, int user) @@ -511,7 +511,7 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var, par->misc &= ~0x40; if (var->sync & FB_SYNC_VERT_HIGH_ACT) par->misc &= ~0x80; - + par->mode = mode; if (mode & MODE_8BPP) @@ -520,8 +520,8 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var, else /* pixel clock == vga clock */ vga16fb_clock_chip(par, &var->pixclock, info, 1, 1); - - var->red.offset = var->green.offset = var->blue.offset = + + var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0; var->red.length = var->green.length = var->blue.length = (par->isVGA) ? 6 : 2; @@ -588,10 +588,10 @@ static int vga16fb_set_par(struct fb_info *info) else atc[VGA_ATC_PEL] = info->var.xoffset & 7; atc[VGA_ATC_COLOR_PAGE] = 0x00; - + if (par->mode & MODE_TEXT) { - fh = 16; // FIXME !!! Fudge font height. - par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] + fh = 16; // FIXME !!! Fudge font height. + par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] & ~0x1F) | (fh - 1); } @@ -602,10 +602,10 @@ static int vga16fb_set_par(struct fb_info *info) vga_io_w(EGA_GFX_E0, 0x00); vga_io_w(EGA_GFX_E1, 0x01); } - + /* update misc output register */ vga_io_w(VGA_MIS_W, par->misc); - + /* synchronous reset on */ vga_io_wseq(0x00, 0x01); @@ -617,7 +617,7 @@ static int vga16fb_set_par(struct fb_info *info) for (i = 2; i < VGA_SEQ_C; i++) { vga_io_wseq(i, seq[i]); } - + /* synchronous reset off */ vga_io_wseq(0x00, 0x03); @@ -628,12 +628,12 @@ static int vga16fb_set_par(struct fb_info *info) for (i = 0; i < VGA_CRTC_REGS; i++) { vga_io_wcrt(i, par->crtc[i]); } - + /* write graphics controller registers */ for (i = 0; i < VGA_GFX_C; i++) { vga_io_wgfx(i, gdc[i]); } - + /* write attribute controller registers */ for (i = 0; i < VGA_ATT_C; i++) { vga_io_r(VGA_IS1_RC); /* reset flip-flop */ @@ -656,7 +656,7 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b { static const unsigned char map[] = { 000, 001, 010, 011 }; int val; - + if (regno >= 16) return; val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2); @@ -687,17 +687,17 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, * (according to the entries in the `var' structure). Return * != 0 for invalid regno. */ - + if (regno >= 256) return 1; gray = info->var.grayscale; - + if (gray) { /* gray = 0.30*R + 0.59*G + 0.11*B */ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; } - if (par->isVGA) + if (par->isVGA) vga16_setpalette(regno,red,green,blue); else ega16_setpalette(regno,red,green,blue); @@ -705,7 +705,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, } static int vga16fb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info) + struct fb_info *info) { vga16fb_pan_var(info, var); return 0; @@ -720,7 +720,7 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode) { unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); - + /* save original values of VGA controller registers */ if(!par->vesa_blanked) { par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R); @@ -776,7 +776,7 @@ static void vga_vesa_unblank(struct vga16fb_par *par) { unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); - + /* restore original values of VGA controller registers */ vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO); @@ -962,7 +962,7 @@ static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec } break; } - } else + } else vga_8planes_fillrect(info, rect); break; case FB_TYPE_PACKED_PIXELS: @@ -1029,7 +1029,7 @@ static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; + u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; int x, x2, y2, old_dx, old_dy, vxres, vyres; int height, width, line_ofs; char __iomem *dst = NULL; @@ -1094,9 +1094,9 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are dst += line_ofs; } } else { - dst = info->screen_base + (dx/8) + width + + dst = info->screen_base + (dx/8) + width + (dy + height - 1) * info->fix.line_length; - src = info->screen_base + (sx/8) + width + + src = info->screen_base + (sx/8) + width + (sy + height - 1) * info->fix.line_length; while (height--) { for (x = 0; x < width; x++) { @@ -1109,7 +1109,7 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are dst -= line_ofs; } } - } else + } else vga_8planes_copyarea(info, area); break; case FB_TYPE_PACKED_PIXELS: @@ -1182,7 +1182,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im setsr(0xf); setcolor(image->fg_color); selectmask(); - + setmask(0xff); writeb(image->bg_color, where); rmb(); @@ -1191,7 +1191,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im wmb(); for (y = 0; y < image->height; y++) { dst = where; - for (x = image->width/8; x--;) + for (x = image->width/8; x--;) writeb(*cdat++, dst++); where += info->fix.line_length; } @@ -1202,7 +1202,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im setsr(0xf); setcolor(image->bg_color); selectmask(); - + setmask(0xff); for (y = 0; y < image->height; y++) { dst = where; @@ -1218,7 +1218,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im where += info->fix.line_length; } } - } else + } else vga_8planes_imageblit(info, image); break; case FB_TYPE_PACKED_PIXELS: @@ -1231,7 +1231,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image) { /* - * Draw logo + * Draw logo */ struct vga16fb_par *par = info->par; char __iomem *where = @@ -1248,7 +1248,7 @@ static void vga_imageblit_color(struct fb_info *info, const struct fb_image *ima setsr(0xf); setop(0); setmode(0); - + for (y = 0; y < image->height; y++) { for (x = 0; x < image->width; x++) { dst = where + x/8; @@ -1272,7 +1272,7 @@ static void vga_imageblit_color(struct fb_info *info, const struct fb_image *ima break; } } - + static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image) { if (image->depth == 1) @@ -1308,10 +1308,10 @@ static const struct fb_ops vga16fb_ops = { static int __init vga16fb_setup(char *options) { char *this_opt; - + if (!options || !*options) return 0; - + while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; } @@ -1361,10 +1361,10 @@ static int vga16fb_probe(struct platform_device *dev) par->vesa_blanked = 0; i = par->isVGA? 6 : 2; - + vga16fb_defined.red.length = i; vga16fb_defined.green.length = i; - vga16fb_defined.blue.length = i; + vga16fb_defined.blue.length = i; /* name should not depend on EGA/VGA */ info->fbops = &vga16fb_ops; diff --git a/include/video/vga.h b/include/video/vga.h index d334e64c1c19..ef8e9fa9b9bd 100644 --- a/include/video/vga.h +++ b/include/video/vga.h @@ -2,15 +2,15 @@ * linux/include/video/vga.h -- standard VGA chipset interaction * * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> - * + * * Copyright history from vga16fb.c: * Copyright 1999 Ben Pfaff and Petr Vandrovec - * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm + * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm * Based on VESA framebuffer (c) 1998 Gerd Knorr * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this - * archive for more details. + * archive for more details. * */ @@ -190,7 +190,7 @@ struct vgastate { __u32 num_gfx; /* number of gfx registers, 0 for default */ __u32 num_seq; /* number of seq registers, 0 for default */ void *vidstate; -}; +}; extern int save_vga(struct vgastate *state); extern int restore_vga(struct vgastate *state); @@ -198,7 +198,7 @@ extern int restore_vga(struct vgastate *state); /* * generic VGA port read/write */ - + static inline unsigned char vga_io_r (unsigned short port) { return inb_p(port); @@ -261,7 +261,7 @@ static inline void vga_w_fast (void __iomem *regbase, unsigned short port, /* * VGA CRTC register read/write */ - + static inline unsigned char vga_rcrt (void __iomem *regbase, unsigned char reg) { vga_w (regbase, VGA_CRT_IC, reg); @@ -314,7 +314,7 @@ static inline void vga_mm_wcrt (void __iomem *regbase, unsigned char reg, unsign /* * VGA sequencer register read/write */ - + static inline unsigned char vga_rseq (void __iomem *regbase, unsigned char reg) { vga_w (regbase, VGA_SEQ_I, reg); @@ -366,7 +366,7 @@ static inline void vga_mm_wseq (void __iomem *regbase, unsigned char reg, unsign /* * VGA graphics controller register read/write */ - + static inline unsigned char vga_rgfx (void __iomem *regbase, unsigned char reg) { vga_w (regbase, VGA_GFX_I, reg); @@ -419,7 +419,7 @@ static inline void vga_mm_wgfx (void __iomem *regbase, unsigned char reg, unsign /* * VGA attribute controller register read/write */ - + static inline unsigned char vga_rattr (void __iomem *regbase, unsigned char reg) { vga_w (regbase, VGA_ATT_IW, reg); From 0db5b61e0dc07cee121e5a04932ca7f5d0b62f6a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:13 +0200 Subject: [PATCH 154/396] fbdev/vga16fb: Create EGA/VGA devices in sysfb code Move the device-creation from vga16fb to sysfb code. The driver's videomode checks are independent from device creation, so move them into vga16fb's probe function. This will allow to create the module init/exit code automatically. The vga16fb driver requires a screen_info for type VIDEO_TYPE_VGAC or VIDEO_TYPE_EGAC. Such code is nowhere present in the kernel, except for some MIPS systems. It's not clear if the vga16fb driver actually works in practice. v2: * keep driver name to "vga16fb" (Javier) * give rational for moving mode checks (Javier) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-3-tzimmermann@suse.de --- drivers/firmware/sysfb.c | 4 +++ drivers/video/fbdev/vga16fb.c | 57 +++++++++++++++++------------------ 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c index 1f276f108cc9..3fd3563d962b 100644 --- a/drivers/firmware/sysfb.c +++ b/drivers/firmware/sysfb.c @@ -94,6 +94,10 @@ static __init int sysfb_init(void) name = "efi-framebuffer"; else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB) name = "vesa-framebuffer"; + else if (si->orig_video_isVGA == VIDEO_TYPE_VGAC) + name = "vga-framebuffer"; + else if (si->orig_video_isVGA == VIDEO_TYPE_EGAC) + name = "ega-framebuffer"; else name = "platform-framebuffer"; diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c index faf76972114d..9e614c1db03d 100644 --- a/drivers/video/fbdev/vga16fb.c +++ b/drivers/video/fbdev/vga16fb.c @@ -185,19 +185,19 @@ static inline void setindex(int index) } /* Check if the video mode is supported by the driver */ -static inline int check_mode_supported(void) +static inline int check_mode_supported(const struct screen_info *si) { /* non-x86 architectures treat orig_video_isVGA as a boolean flag */ #if defined(CONFIG_X86) /* only EGA and VGA in 16 color graphic mode are supported */ - if (screen_info.orig_video_isVGA != VIDEO_TYPE_EGAC && - screen_info.orig_video_isVGA != VIDEO_TYPE_VGAC) + if (si->orig_video_isVGA != VIDEO_TYPE_EGAC && + si->orig_video_isVGA != VIDEO_TYPE_VGAC) return -ENODEV; - if (screen_info.orig_video_mode != 0x0D && /* 320x200/4 (EGA) */ - screen_info.orig_video_mode != 0x0E && /* 640x200/4 (EGA) */ - screen_info.orig_video_mode != 0x10 && /* 640x350/4 (EGA) */ - screen_info.orig_video_mode != 0x12) /* 640x480/4 (VGA) */ + if (si->orig_video_mode != 0x0D && /* 320x200/4 (EGA) */ + si->orig_video_mode != 0x0E && /* 640x200/4 (EGA) */ + si->orig_video_mode != 0x10 && /* 640x350/4 (EGA) */ + si->orig_video_mode != 0x12) /* 640x480/4 (VGA) */ return -ENODEV; #endif return 0; @@ -1321,11 +1321,20 @@ static int __init vga16fb_setup(char *options) static int vga16fb_probe(struct platform_device *dev) { + struct screen_info *si; struct fb_info *info; struct vga16fb_par *par; int i; int ret = 0; + si = dev_get_platdata(&dev->dev); + if (!si) + return -ENODEV; + + ret = check_mode_supported(si); + if (ret) + return ret; + printk(KERN_DEBUG "vga16fb: initializing\n"); info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev); @@ -1352,10 +1361,10 @@ static int vga16fb_probe(struct platform_device *dev) par = info->par; #if defined(CONFIG_X86) - par->isVGA = screen_info.orig_video_isVGA == VIDEO_TYPE_VGAC; + par->isVGA = si->orig_video_isVGA == VIDEO_TYPE_VGAC; #else /* non-x86 architectures treat orig_video_isVGA as a boolean flag */ - par->isVGA = screen_info.orig_video_isVGA; + par->isVGA = si->orig_video_isVGA; #endif par->palette_blanked = 0; par->vesa_blanked = 0; @@ -1425,16 +1434,21 @@ static int vga16fb_remove(struct platform_device *dev) return 0; } +static const struct platform_device_id vga16fb_driver_id_table[] = { + {"ega-framebuffer", 0}, + {"vga-framebuffer", 0}, + { } +}; + static struct platform_driver vga16fb_driver = { .probe = vga16fb_probe, .remove = vga16fb_remove, .driver = { .name = "vga16fb", }, + .id_table = vga16fb_driver_id_table, }; -static struct platform_device *vga16fb_device; - static int __init vga16fb_init(void) { int ret; @@ -1447,32 +1461,15 @@ static int __init vga16fb_init(void) vga16fb_setup(option); #endif - ret = check_mode_supported(); + ret = platform_driver_register(&vga16fb_driver); if (ret) return ret; - ret = platform_driver_register(&vga16fb_driver); - - if (!ret) { - vga16fb_device = platform_device_alloc("vga16fb", 0); - - if (vga16fb_device) - ret = platform_device_add(vga16fb_device); - else - ret = -ENOMEM; - - if (ret) { - platform_device_put(vga16fb_device); - platform_driver_unregister(&vga16fb_driver); - } - } - - return ret; + return 0; } static void __exit vga16fb_exit(void) { - platform_device_unregister(vga16fb_device); platform_driver_unregister(&vga16fb_driver); } From 8a611e08257afb9ab5814d5c19239bf40e5030f4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:14 +0200 Subject: [PATCH 155/396] fbdev/vga16fb: Auto-generate module init/exit code Move vgag16fb's option parsing into the driver's probe function and generate the rest of the module's init/exit functions from macros. Keep the options code, although there are no options defined. v2: * no options are supported, remove the code (Javier) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-4-tzimmermann@suse.de --- drivers/video/fbdev/vga16fb.c | 41 +---------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c index 9e614c1db03d..3312b6a4e00d 100644 --- a/drivers/video/fbdev/vga16fb.c +++ b/drivers/video/fbdev/vga16fb.c @@ -1304,21 +1304,6 @@ static const struct fb_ops vga16fb_ops = { .fb_imageblit = vga16fb_imageblit, }; -#ifndef MODULE -static int __init vga16fb_setup(char *options) -{ - char *this_opt; - - if (!options || !*options) - return 0; - - while ((this_opt = strsep(&options, ",")) != NULL) { - if (!*this_opt) continue; - } - return 0; -} -#endif - static int vga16fb_probe(struct platform_device *dev) { struct screen_info *si; @@ -1449,31 +1434,7 @@ static struct platform_driver vga16fb_driver = { .id_table = vga16fb_driver_id_table, }; -static int __init vga16fb_init(void) -{ - int ret; -#ifndef MODULE - char *option = NULL; - - if (fb_get_options("vga16fb", &option)) - return -ENODEV; - - vga16fb_setup(option); -#endif - - ret = platform_driver_register(&vga16fb_driver); - if (ret) - return ret; - - return 0; -} - -static void __exit vga16fb_exit(void) -{ - platform_driver_unregister(&vga16fb_driver); -} +module_platform_driver(vga16fb_driver); MODULE_DESCRIPTION("Legacy VGA framebuffer device driver"); MODULE_LICENSE("GPL"); -module_init(vga16fb_init); -module_exit(vga16fb_exit); From 9d69ef1838150c7d87afc1a87aa658c637217585 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:15 +0200 Subject: [PATCH 156/396] fbdev/core: Remove remove_conflicting_pci_framebuffers() Remove remove_conflicting_pci_framebuffers() and implement similar functionality in aperture_remove_conflicting_pci_device(), which was the only caller. Removes an otherwise unused interface and streamlines the aperture helper. No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-5-tzimmermann@suse.de --- drivers/video/aperture.c | 32 ++++++++++++--------- drivers/video/fbdev/core/fbmem.c | 48 -------------------------------- include/linux/fb.h | 2 -- 3 files changed, 19 insertions(+), 63 deletions(-) diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c index 538f2d40acda..f42a0d8bc211 100644 --- a/drivers/video/aperture.c +++ b/drivers/video/aperture.c @@ -321,30 +321,36 @@ EXPORT_SYMBOL(aperture_remove_conflicting_devices); */ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name) { + bool primary = false; resource_size_t base, size; int bar, ret; +#ifdef CONFIG_X86 + primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; +#endif + + for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) { + if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) + continue; + + base = pci_resource_start(pdev, bar); + size = pci_resource_len(pdev, bar); + ret = aperture_remove_conflicting_devices(base, size, primary, name); + if (ret) + break; + } + + if (ret) + return ret; + /* * WARNING: Apparently we must kick fbdev drivers before vgacon, * otherwise the vga fbdev driver falls over. */ -#if IS_REACHABLE(CONFIG_FB) - ret = remove_conflicting_pci_framebuffers(pdev, name); - if (ret) - return ret; -#endif ret = vga_remove_vgacon(pdev); if (ret) return ret; - for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) { - if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) - continue; - base = pci_resource_start(pdev, bar); - size = pci_resource_len(pdev, bar); - aperture_detach_devices(base, size); - } - return 0; } diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 02b0cf2cfafe..c8f9532cc6b4 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1799,54 +1799,6 @@ int remove_conflicting_framebuffers(struct apertures_struct *a, } EXPORT_SYMBOL(remove_conflicting_framebuffers); -/** - * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices - * @pdev: PCI device - * @name: requesting driver name - * - * This function removes framebuffer devices (eg. initialized by firmware) - * using memory range configured for any of @pdev's memory bars. - * - * The function assumes that PCI device with shadowed ROM drives a primary - * display and so kicks out vga16fb. - */ -int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name) -{ - struct apertures_struct *ap; - bool primary = false; - int err, idx, bar; - - for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) { - if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) - continue; - idx++; - } - - ap = alloc_apertures(idx); - if (!ap) - return -ENOMEM; - - for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) { - if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) - continue; - ap->ranges[idx].base = pci_resource_start(pdev, bar); - ap->ranges[idx].size = pci_resource_len(pdev, bar); - pci_dbg(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar, - (unsigned long)pci_resource_start(pdev, bar), - (unsigned long)pci_resource_end(pdev, bar)); - idx++; - } - -#ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & - IORESOURCE_ROM_SHADOW; -#endif - err = remove_conflicting_framebuffers(ap, name, primary); - kfree(ap); - return err; -} -EXPORT_SYMBOL(remove_conflicting_pci_framebuffers); - /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure diff --git a/include/linux/fb.h b/include/linux/fb.h index 07fcd0e56682..b91c77016560 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -615,8 +615,6 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern void unregister_framebuffer(struct fb_info *fb_info); -extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, - const char *name); extern int remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); From 8d69d008f44cb96050c35e64fe940a22dd6b0113 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:16 +0200 Subject: [PATCH 157/396] fbdev: Convert drivers to aperture helpers Convert fbdev drivers from fbdev's remove_conflicting_framebuffers() to the framework-independent aperture_remove_conflicting_devices(). Calling this function will also remove conflicting DRM drivers. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-6-tzimmermann@suse.de --- drivers/staging/sm750fb/sm750.c | 15 +++++---------- drivers/video/fbdev/aty/radeon_base.c | 17 ++++------------- drivers/video/fbdev/hyperv_fb.c | 6 ++++-- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index dbd1159a2ef0..ce04c38f6afd 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include <linux/aperture.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/errno.h> @@ -987,22 +988,16 @@ release_fb: static int lynxfb_kick_out_firmware_fb(struct pci_dev *pdev) { - struct apertures_struct *ap; + resource_size_t base = pci_resource_start(pdev, 0); + resource_size_t size = pci_resource_len(pdev, 0); bool primary = false; - ap = alloc_apertures(1); - if (!ap) - return -ENOMEM; - - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); #ifdef CONFIG_X86 primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; #endif - remove_conflicting_framebuffers(ap, "sm750_fb1", primary); - kfree(ap); - return 0; + + return aperture_remove_conflicting_devices(base, size, primary, "sm750_fb1"); } static int lynxfb_pci_probe(struct pci_dev *pdev, diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index b311c07fe66d..e5e362b8c9da 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -54,6 +54,7 @@ #include "radeonfb.h" +#include <linux/aperture.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -2239,20 +2240,10 @@ static const struct bin_attribute edid2_attr = { static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) { - struct apertures_struct *ap; + resource_size_t base = pci_resource_start(pdev, 0); + resource_size_t size = pci_resource_len(pdev, 0); - ap = alloc_apertures(1); - if (!ap) - return -ENOMEM; - - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); - - remove_conflicting_framebuffers(ap, KBUILD_MODNAME, false); - - kfree(ap); - - return 0; + return aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME, false); } static int radeonfb_pci_register(struct pci_dev *pdev, diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 886c564787f1..a944a6620527 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -45,6 +45,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/vmalloc.h> @@ -1074,8 +1075,9 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) info->screen_size = dio_fb_size; getmem_done: - remove_conflicting_framebuffers(info->apertures, - KBUILD_MODNAME, false); + aperture_remove_conflicting_devices(info->apertures->ranges[0].base, + info->apertures->ranges[0].size, + KBUILD_MODNAME, false); if (gen2vm) { /* framebuffer is reallocated, clear screen_info to avoid misuse from kexec */ From 145eed48de278007f646b908fd70ac59d24ed81a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:17 +0200 Subject: [PATCH 158/396] fbdev: Remove conflicting devices on PCI bus Remove firmware devices on the PCI bus, by calling aperture_remove_conflicting_pci_devices() in the probe function of each related fbdev driver. iSo far, most of these drivers did not remove conflicting VESA or EFI devices, or outride failed for resource conflicts (i.e., matroxfb.) This must have been broken for quite some time. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-7-tzimmermann@suse.de --- drivers/video/fbdev/arkfb.c | 5 +++++ drivers/video/fbdev/asiliantfb.c | 5 +++++ drivers/video/fbdev/aty/aty128fb.c | 5 +++++ drivers/video/fbdev/aty/atyfb_base.c | 7 ++++++- drivers/video/fbdev/carminefb.c | 5 +++++ drivers/video/fbdev/chipsfb.c | 7 ++++++- drivers/video/fbdev/cirrusfb.c | 5 +++++ drivers/video/fbdev/cyber2000fb.c | 5 +++++ drivers/video/fbdev/geode/gx1fb_core.c | 5 +++++ drivers/video/fbdev/geode/gxfb_core.c | 5 +++++ drivers/video/fbdev/geode/lxfb_core.c | 5 +++++ drivers/video/fbdev/gxt4500.c | 5 +++++ drivers/video/fbdev/i740fb.c | 5 +++++ drivers/video/fbdev/i810/i810_main.c | 5 +++++ drivers/video/fbdev/imsttfb.c | 8 +++++++- drivers/video/fbdev/intelfb/intelfbdrv.c | 5 +++++ drivers/video/fbdev/kyro/fbdev.c | 5 +++++ drivers/video/fbdev/matrox/matroxfb_base.c | 5 +++++ drivers/video/fbdev/mb862xx/mb862xxfbdrv.c | 5 +++++ drivers/video/fbdev/neofb.c | 5 +++++ drivers/video/fbdev/nvidia/nvidia.c | 7 ++++++- drivers/video/fbdev/pm2fb.c | 5 +++++ drivers/video/fbdev/pm3fb.c | 5 +++++ drivers/video/fbdev/pvr2fb.c | 5 +++++ drivers/video/fbdev/riva/fbdev.c | 5 +++++ drivers/video/fbdev/s3fb.c | 5 +++++ drivers/video/fbdev/savage/savagefb_driver.c | 5 +++++ drivers/video/fbdev/sis/sis_main.c | 5 +++++ drivers/video/fbdev/skeletonfb.c | 8 ++++++++ drivers/video/fbdev/sm712fb.c | 5 +++++ drivers/video/fbdev/sstfb.c | 5 +++++ drivers/video/fbdev/sunxvr2500.c | 5 +++++ drivers/video/fbdev/sunxvr500.c | 5 +++++ drivers/video/fbdev/tdfxfb.c | 5 +++++ drivers/video/fbdev/tgafb.c | 7 +++++++ drivers/video/fbdev/tridentfb.c | 5 +++++ drivers/video/fbdev/vermilion/vermilion.c | 7 ++++++- drivers/video/fbdev/via/via-core.c | 5 +++++ drivers/video/fbdev/vt8623fb.c | 5 +++++ 39 files changed, 206 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbdev/arkfb.c b/drivers/video/fbdev/arkfb.c index eb3e47c58c5f..453daa072f53 100644 --- a/drivers/video/fbdev/arkfb.c +++ b/drivers/video/fbdev/arkfb.c @@ -11,6 +11,7 @@ * Code is based on s3fb */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -949,6 +950,10 @@ static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) int rc; u8 regval; + rc = aperture_remove_conflicting_pci_devices(dev, "arkfb"); + if (rc < 0) + return rc; + /* Ignore secondary VGA device because there is no VGA arbitration */ if (! svga_primary_device(dev)) { dev_info(&(dev->dev), "ignoring secondary device\n"); diff --git a/drivers/video/fbdev/asiliantfb.c b/drivers/video/fbdev/asiliantfb.c index f8ef62542f7f..3818437a8f69 100644 --- a/drivers/video/fbdev/asiliantfb.c +++ b/drivers/video/fbdev/asiliantfb.c @@ -29,6 +29,7 @@ * more details. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -545,6 +546,10 @@ static int asiliantfb_pci_init(struct pci_dev *dp, struct fb_info *p; int err; + err = aperture_remove_conflicting_pci_devices(dp, "asiliantfb"); + if (err) + return err; + if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) return -ENODEV; addr = pci_resource_start(dp, 0); diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c index 5cdbbba2a013..57e398fe7a81 100644 --- a/drivers/video/fbdev/aty/aty128fb.c +++ b/drivers/video/fbdev/aty/aty128fb.c @@ -47,6 +47,7 @@ */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -2055,6 +2056,10 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *bios = NULL; #endif + err = aperture_remove_conflicting_pci_devices(pdev, "aty128fb"); + if (err) + return err; + /* Enable device in PCI config */ if ((err = pci_enable_device(pdev))) { printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n", diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index a3e6faed7745..4804b6e9f3f4 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -48,6 +48,7 @@ ******************************************************************************/ +#include <linux/aperture.h> #include <linux/compat.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -3533,7 +3534,11 @@ static int atyfb_pci_probe(struct pci_dev *pdev, struct fb_info *info; struct resource *rp; struct atyfb_par *par; - int rc = -ENOMEM; + int rc; + + rc = aperture_remove_conflicting_pci_devices(pdev, "atyfb"); + if (rc) + return rc; /* Enable device in PCI config */ if (pci_enable_device(pdev)) { diff --git a/drivers/video/fbdev/carminefb.c b/drivers/video/fbdev/carminefb.c index 3a1c2e0739a1..4651b48a87f9 100644 --- a/drivers/video/fbdev/carminefb.c +++ b/drivers/video/fbdev/carminefb.c @@ -7,6 +7,7 @@ * - FB1 is display 1 with unique memory area * - both display use 32 bit colors */ +#include <linux/aperture.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/fb.h> @@ -614,6 +615,10 @@ static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent) struct fb_info *info; int ret; + ret = aperture_remove_conflicting_pci_devices(dev, "carminefb"); + if (ret) + return ret; + ret = pci_enable_device(dev); if (ret) return ret; diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c index 618fb6dbbedb..5ad64714d39e 100644 --- a/drivers/video/fbdev/chipsfb.c +++ b/drivers/video/fbdev/chipsfb.c @@ -14,6 +14,7 @@ * more details. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -351,7 +352,11 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) struct fb_info *p; unsigned long addr; unsigned short cmd; - int rc = -ENODEV; + int rc; + + rc = aperture_remove_conflicting_pci_devices(dp, "chipsfb"); + if (rc) + return rc; if (pci_enable_device(dp) < 0) { dev_err(&dp->dev, "Cannot enable PCI device\n"); diff --git a/drivers/video/fbdev/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c index 51e072c03e1c..4ff6f624f912 100644 --- a/drivers/video/fbdev/cirrusfb.c +++ b/drivers/video/fbdev/cirrusfb.c @@ -34,6 +34,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -2085,6 +2086,10 @@ static int cirrusfb_pci_register(struct pci_dev *pdev, unsigned long board_addr, board_size; int ret; + ret = aperture_remove_conflicting_pci_devices(pdev, "cirrusfb"); + if (ret) + return ret; + ret = pci_enable_device(pdev); if (ret < 0) { printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n"); diff --git a/drivers/video/fbdev/cyber2000fb.c b/drivers/video/fbdev/cyber2000fb.c index d45355b9a58c..be7bcf95c96a 100644 --- a/drivers/video/fbdev/cyber2000fb.c +++ b/drivers/video/fbdev/cyber2000fb.c @@ -33,6 +33,7 @@ * (which, incidentally, is about the same saving as a 2.5in hard disk * entering standby mode.) */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1720,6 +1721,10 @@ static int cyberpro_pci_probe(struct pci_dev *dev, sprintf(name, "CyberPro%4X", id->device); + err = aperture_remove_conflicting_pci_devices(dev, name); + if (err) + return err; + err = pci_enable_device(dev); if (err) return err; diff --git a/drivers/video/fbdev/geode/gx1fb_core.c b/drivers/video/fbdev/geode/gx1fb_core.c index 5d34d89fb665..4cac7e3bb1a0 100644 --- a/drivers/video/fbdev/geode/gx1fb_core.c +++ b/drivers/video/fbdev/geode/gx1fb_core.c @@ -6,6 +6,7 @@ * Copyright (C) 2005 Arcom Control Systems Ltd. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -320,6 +321,10 @@ static int gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct fb_info *info; int ret; + ret = aperture_remove_conflicting_pci_devices(pdev, "gx1fb"); + if (ret) + return ret; + info = gx1fb_init_fbinfo(&pdev->dev); if (!info) return -ENOMEM; diff --git a/drivers/video/fbdev/geode/gxfb_core.c b/drivers/video/fbdev/geode/gxfb_core.c index 44089b331f91..2527bd80ec5f 100644 --- a/drivers/video/fbdev/geode/gxfb_core.c +++ b/drivers/video/fbdev/geode/gxfb_core.c @@ -15,6 +15,7 @@ * * 16 MiB of framebuffer memory is assumed to be available. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -364,6 +365,10 @@ static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct fb_videomode *modedb_ptr; unsigned int modedb_size; + ret = aperture_remove_conflicting_pci_devices(pdev, "gxfb"); + if (ret) + return ret; + info = gxfb_init_fbinfo(&pdev->dev); if (!info) return -ENOMEM; diff --git a/drivers/video/fbdev/geode/lxfb_core.c b/drivers/video/fbdev/geode/lxfb_core.c index 66c81262d18f..9d26592dbfce 100644 --- a/drivers/video/fbdev/geode/lxfb_core.c +++ b/drivers/video/fbdev/geode/lxfb_core.c @@ -6,6 +6,7 @@ * Built from gxfb (which is Copyright (C) 2006 Arcom Control Systems Ltd.) */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -484,6 +485,10 @@ static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct fb_videomode *modedb_ptr; unsigned int modedb_size; + ret = aperture_remove_conflicting_pci_devices(pdev, "lxfb"); + if (ret) + return ret; + info = lxfb_init_fbinfo(&pdev->dev); if (info == NULL) diff --git a/drivers/video/fbdev/gxt4500.c b/drivers/video/fbdev/gxt4500.c index e5475ae1e158..f0d36a4fdaef 100644 --- a/drivers/video/fbdev/gxt4500.c +++ b/drivers/video/fbdev/gxt4500.c @@ -6,6 +6,7 @@ * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org> */ +#include <linux/aperture.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/fb.h> @@ -621,6 +622,10 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct fb_var_screeninfo var; enum gxt_cards cardtype; + err = aperture_remove_conflicting_pci_devices(pdev, "gxt4500fb"); + if (err) + return err; + err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n", diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c index 09dd85553d4f..23329de28e77 100644 --- a/drivers/video/fbdev/i740fb.c +++ b/drivers/video/fbdev/i740fb.c @@ -12,6 +12,7 @@ * i740fb by Patrick LERDA, v0.9 */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1008,6 +1009,10 @@ static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent) bool found = false; u8 *edid; + ret = aperture_remove_conflicting_pci_devices(dev, "i740fb"); + if (ret) + return ret; + info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev)); if (!info) return -ENOMEM; diff --git a/drivers/video/fbdev/i810/i810_main.c b/drivers/video/fbdev/i810/i810_main.c index 41a86efca516..ff09f8c20bfc 100644 --- a/drivers/video/fbdev/i810/i810_main.c +++ b/drivers/video/fbdev/i810/i810_main.c @@ -28,6 +28,7 @@ * more details. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -2016,6 +2017,10 @@ static int i810fb_init_pci(struct pci_dev *dev, struct fb_videomode mode; int err = -1, vfreq, hfreq, pixclock; + err = aperture_remove_conflicting_pci_devices(dev, "i810fb"); + if (err) + return err; + info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev); if (!info) return -ENOMEM; diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index f489386855c0..d7edb9c5d3a3 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -16,6 +16,7 @@ * more details. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1469,7 +1470,12 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct imstt_par *par; struct fb_info *info; struct device_node *dp; - int ret = -ENOMEM; + int ret; + + ret = aperture_remove_conflicting_pci_devices(pdev, "imsttfb"); + if (ret) + return ret; + ret = -ENOMEM; dp = pci_device_to_OF_node(pdev); if(dp) diff --git a/drivers/video/fbdev/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c index 5647fca8c49a..d4a2891a9a7a 100644 --- a/drivers/video/fbdev/intelfb/intelfbdrv.c +++ b/drivers/video/fbdev/intelfb/intelfbdrv.c @@ -107,6 +107,7 @@ * Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>) */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -483,6 +484,10 @@ static int intelfb_pci_register(struct pci_dev *pdev, DBG_MSG("intelfb_pci_register\n"); + err = aperture_remove_conflicting_pci_devices(pdev, "intelfb"); + if (err) + return err; + num_registered++; if (num_registered != 1) { ERR_MSG("Attempted to register %d devices " diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c index d57772f96ad2..b4b93054c520 100644 --- a/drivers/video/fbdev/kyro/fbdev.c +++ b/drivers/video/fbdev/kyro/fbdev.c @@ -9,6 +9,7 @@ * for more details. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -676,6 +677,10 @@ static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) unsigned long size; int err; + err = aperture_remove_conflicting_pci_devices(pdev, "kyrofb"); + if (err) + return err; + if ((err = pci_enable_device(pdev))) { printk(KERN_WARNING "kyrofb: Can't enable pdev: %d\n", err); return err; diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c index 236521b19daf..3e26346c05a2 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.c +++ b/drivers/video/fbdev/matrox/matroxfb_base.c @@ -100,6 +100,7 @@ * */ +#include <linux/aperture.h> #include <linux/version.h> #include "matroxfb_base.h" @@ -2044,6 +2045,10 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm u_int32_t cmd; DBG(__func__) + err = aperture_remove_conflicting_pci_devices(pdev, "matroxfb"); + if (err) + return err; + svid = pdev->subsystem_vendor; sid = pdev->subsystem_device; for (b = dev_list; b->vendor; b++) { diff --git a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c index a7508f5be343..96800c9c9cd9 100644 --- a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c @@ -10,6 +10,7 @@ #undef DEBUG +#include <linux/aperture.h> #include <linux/fb.h> #include <linux/delay.h> #include <linux/uaccess.h> @@ -999,6 +1000,10 @@ static int mb862xx_pci_probe(struct pci_dev *pdev, struct device *dev = &pdev->dev; int ret; + ret = aperture_remove_conflicting_pci_devices(pdev, "mb862xxfb"); + if (ret) + return ret; + ret = pci_enable_device(pdev); if (ret < 0) { dev_err(dev, "Cannot enable PCI device\n"); diff --git a/drivers/video/fbdev/neofb.c b/drivers/video/fbdev/neofb.c index 8ad2a79623af..93a2d2d1abe8 100644 --- a/drivers/video/fbdev/neofb.c +++ b/drivers/video/fbdev/neofb.c @@ -54,6 +54,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -2029,6 +2030,10 @@ static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id) DBG("neofb_probe"); + err = aperture_remove_conflicting_pci_devices(dev, "neofb"); + if (err) + return err; + err = pci_enable_device(dev); if (err) return err; diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c index a372a183c1f0..329e2e8133c6 100644 --- a/drivers/video/fbdev/nvidia/nvidia.c +++ b/drivers/video/fbdev/nvidia/nvidia.c @@ -9,6 +9,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1276,11 +1277,15 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent) struct nvidia_par *par; struct fb_info *info; unsigned short cmd; - + int ret; NVTRACE_ENTER(); assert(pd != NULL); + ret = aperture_remove_conflicting_pci_devices(pd, "nvidiafb"); + if (ret) + return ret; + info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev); if (!info) diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c index d3be2c64f1c0..bc80d8498aeb 100644 --- a/drivers/video/fbdev/pm2fb.c +++ b/drivers/video/fbdev/pm2fb.c @@ -27,6 +27,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -1516,6 +1517,10 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) int err; int retval = -ENXIO; + err = aperture_remove_conflicting_pci_devices(pdev, "pm2fb"); + if (err) + return err; + err = pci_enable_device(pdev); if (err) { printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err); diff --git a/drivers/video/fbdev/pm3fb.c b/drivers/video/fbdev/pm3fb.c index a8faf46adeb1..ba69846d444f 100644 --- a/drivers/video/fbdev/pm3fb.c +++ b/drivers/video/fbdev/pm3fb.c @@ -22,6 +22,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1315,6 +1316,10 @@ static int pm3fb_probe(struct pci_dev *dev, const struct pci_device_id *ent) int err; int retval = -ENXIO; + err = aperture_remove_conflicting_pci_devices(dev, "pm3fb"); + if (err) + return err; + err = pci_enable_device(dev); if (err) { printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err); diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index f4add36cb5f4..b73ad14efa20 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c @@ -45,6 +45,7 @@ #undef DEBUG +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -942,6 +943,10 @@ static int pvr2fb_pci_probe(struct pci_dev *pdev, { int ret; + ret = aperture_remove_conflicting_pci_devices(pdev, "pvrfb"); + if (ret) + return ret; + ret = pci_enable_device(pdev); if (ret) { printk(KERN_ERR "pvr2fb: PCI enable failed\n"); diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index 5bafc44c591b..0ea74e28f915 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -29,6 +29,7 @@ * doublescan modes are broken */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1898,6 +1899,10 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent) NVTRACE_ENTER(); assert(pd != NULL); + ret = aperture_remove_conflicting_pci_devices(pd, "rivafb"); + if (ret) + return ret; + info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev); if (!info) { ret = -ENOMEM; diff --git a/drivers/video/fbdev/s3fb.c b/drivers/video/fbdev/s3fb.c index b93c8eb02336..f66c4de0e188 100644 --- a/drivers/video/fbdev/s3fb.c +++ b/drivers/video/fbdev/s3fb.c @@ -11,6 +11,7 @@ * which is based on the code of neofb. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1129,6 +1130,10 @@ static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; } + rc = aperture_remove_conflicting_pci_devices(dev, "s3fb"); + if (rc) + return rc; + /* Allocate and fill driver data structure */ info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev)); if (!info) diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c index 8114c921ceb8..b7818b652698 100644 --- a/drivers/video/fbdev/savage/savagefb_driver.c +++ b/drivers/video/fbdev/savage/savagefb_driver.c @@ -41,6 +41,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -2176,6 +2177,10 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id) DBG("savagefb_probe"); + err = aperture_remove_conflicting_pci_devices(dev, "savagefb"); + if (err) + return err; + info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev); if (!info) return -ENOMEM; diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c index f28fd69d5eb7..7114c5c17c91 100644 --- a/drivers/video/fbdev/sis/sis_main.c +++ b/drivers/video/fbdev/sis/sis_main.c @@ -19,6 +19,7 @@ * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -5849,6 +5850,10 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if(sisfb_off) return -ENXIO; + ret = aperture_remove_conflicting_pci_devices(pdev, "sisfb"); + if (ret) + return ret; + sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev); if(!sis_fb_info) return -ENOMEM; diff --git a/drivers/video/fbdev/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c index 304320ce6c6f..125df366e23a 100644 --- a/drivers/video/fbdev/skeletonfb.c +++ b/drivers/video/fbdev/skeletonfb.c @@ -42,6 +42,7 @@ * more details. */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -668,6 +669,13 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent) struct device *device = &dev->dev; /* or &pdev->dev */ int cmap_len, retval; + /* + * Remove firmware-based drivers that create resource conflicts. + */ + retval = aperture_remove_conflicting_pci_devices(pdev, "xxxfb"); + if (retval) + return retval; + /* * Dynamically allocate info and par */ diff --git a/drivers/video/fbdev/sm712fb.c b/drivers/video/fbdev/sm712fb.c index 092a1caa1208..3baf33635e65 100644 --- a/drivers/video/fbdev/sm712fb.c +++ b/drivers/video/fbdev/sm712fb.c @@ -18,6 +18,7 @@ * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips */ +#include <linux/aperture.h> #include <linux/io.h> #include <linux/fb.h> #include <linux/pci.h> @@ -1502,6 +1503,10 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Silicon Motion display driver.\n"); + err = aperture_remove_conflicting_pci_devices(pdev, "smtcfb"); + if (err) + return err; + err = pci_enable_device(pdev); /* enable SMTC chip */ if (err) return err; diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c index 535ef4693cd4..73ca2782ebfc 100644 --- a/drivers/video/fbdev/sstfb.c +++ b/drivers/video/fbdev/sstfb.c @@ -80,6 +80,7 @@ * Includes */ +#include <linux/aperture.h> #include <linux/string.h> #include <linux/kernel.h> #include <linux/module.h> @@ -1326,6 +1327,10 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct sst_spec *spec; int err; + err = aperture_remove_conflicting_pci_devices(pdev, "sstfb"); + if (err) + return err; + /* Enable device in PCI config. */ if ((err=pci_enable_device(pdev))) { printk(KERN_ERR "cannot enable device\n"); diff --git a/drivers/video/fbdev/sunxvr2500.c b/drivers/video/fbdev/sunxvr2500.c index 1d3bacd9d5ac..81d59613ea1f 100644 --- a/drivers/video/fbdev/sunxvr2500.c +++ b/drivers/video/fbdev/sunxvr2500.c @@ -5,6 +5,7 @@ * Copyright (C) 2007 David S. Miller (davem@davemloft.net) */ +#include <linux/aperture.h> #include <linux/kernel.h> #include <linux/fb.h> #include <linux/pci.h> @@ -123,6 +124,10 @@ static int s3d_pci_register(struct pci_dev *pdev, struct s3d_info *sp; int err; + err = aperture_remove_conflicting_pci_devices(pdev, "s3dfb"); + if (err) + return err; + err = pci_enable_device(pdev); if (err < 0) { printk(KERN_ERR "s3d: Cannot enable PCI device %s\n", diff --git a/drivers/video/fbdev/sunxvr500.c b/drivers/video/fbdev/sunxvr500.c index 9daf17b11106..3a51b2a1480c 100644 --- a/drivers/video/fbdev/sunxvr500.c +++ b/drivers/video/fbdev/sunxvr500.c @@ -5,6 +5,7 @@ * Copyright (C) 2007 David S. Miller (davem@davemloft.net) */ +#include <linux/aperture.h> #include <linux/kernel.h> #include <linux/fb.h> #include <linux/pci.h> @@ -249,6 +250,10 @@ static int e3d_pci_register(struct pci_dev *pdev, unsigned int line_length; int err; + err = aperture_remove_conflicting_pci_devices(pdev, "e3dfb"); + if (err) + return err; + of_node = pci_device_to_OF_node(pdev); if (!of_node) { printk(KERN_ERR "e3d: Cannot find OF node of %s\n", diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c index 67e37a62b07c..059e0174e139 100644 --- a/drivers/video/fbdev/tdfxfb.c +++ b/drivers/video/fbdev/tdfxfb.c @@ -64,6 +64,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -1376,6 +1377,10 @@ static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct fb_monspecs *specs; bool found; + err = aperture_remove_conflicting_pci_devices(pdev, "tdfxfb"); + if (err) + return err; + err = pci_enable_device(pdev); if (err) { printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err); diff --git a/drivers/video/fbdev/tgafb.c b/drivers/video/fbdev/tgafb.c index 9266c76783cc..4600138e3bef 100644 --- a/drivers/video/fbdev/tgafb.c +++ b/drivers/video/fbdev/tgafb.c @@ -12,6 +12,7 @@ * more details. */ +#include <linux/aperture.h> #include <linux/bitrev.h> #include <linux/compiler.h> #include <linux/delay.h> @@ -106,6 +107,12 @@ static struct pci_driver tgafb_pci_driver = { static int tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) { + int ret; + + ret = aperture_remove_conflicting_pci_devices(pdev, "tgafb"); + if (ret) + return ret; + return tgafb_register(&pdev->dev); } diff --git a/drivers/video/fbdev/tridentfb.c b/drivers/video/fbdev/tridentfb.c index 319131bd72cf..6813df793c49 100644 --- a/drivers/video/fbdev/tridentfb.c +++ b/drivers/video/fbdev/tridentfb.c @@ -16,6 +16,7 @@ * timing value tweaking so it looks good on every monitor in every mode */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/init.h> @@ -1470,6 +1471,10 @@ static int trident_pci_probe(struct pci_dev *dev, int chip_id; bool found = false; + err = aperture_remove_conflicting_pci_devices(dev, "tridentfb"); + if (err) + return err; + err = pci_enable_device(dev); if (err) return err; diff --git a/drivers/video/fbdev/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c index ff61605b8764..82b36dbb5b1a 100644 --- a/drivers/video/fbdev/vermilion/vermilion.c +++ b/drivers/video/fbdev/vermilion/vermilion.c @@ -14,6 +14,7 @@ * Alan Hourihane <alanh-at-tungstengraphics-dot-com> */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -442,7 +443,11 @@ static int vml_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) struct vml_info *vinfo; struct fb_info *info; struct vml_par *par; - int err = 0; + int err; + + err = aperture_remove_conflicting_pci_devices(dev, "vmlfb"); + if (err) + return err; par = kzalloc(sizeof(*par), GFP_KERNEL); if (par == NULL) diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c index 89d75079b730..2ee8fcae08df 100644 --- a/drivers/video/fbdev/via/via-core.c +++ b/drivers/video/fbdev/via/via-core.c @@ -8,6 +8,7 @@ /* * Core code for the Via multifunction framebuffer device. */ +#include <linux/aperture.h> #include <linux/via-core.h> #include <linux/via_i2c.h> #include <linux/via-gpio.h> @@ -617,6 +618,10 @@ static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int ret; + ret = aperture_remove_conflicting_pci_devices(pdev, "viafb"); + if (ret) + return ret; + ret = pci_enable_device(pdev); if (ret) return ret; diff --git a/drivers/video/fbdev/vt8623fb.c b/drivers/video/fbdev/vt8623fb.c index a92a8c670cf0..62318cef5f8c 100644 --- a/drivers/video/fbdev/vt8623fb.c +++ b/drivers/video/fbdev/vt8623fb.c @@ -12,6 +12,7 @@ * (http://davesdomain.org.uk/viafb/) */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -670,6 +671,10 @@ static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; } + rc = aperture_remove_conflicting_pci_devices(dev, "vt8623fb"); + if (rc) + return rc; + /* Allocate and fill driver data structure */ info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev)); if (!info) From 5e01376124309b4dbd30d413f43c0d9c2f60edea Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:18 +0200 Subject: [PATCH 159/396] video/aperture: Disable and unregister sysfb devices via aperture helpers Call sysfb_disable() before removing conflicting devices in aperture helpers. Fixes sysfb state if fbdev has been disabled. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Fixes: fb84efa28a48 ("drm/aperture: Run fbdev removal before internal helpers") Cc: Zack Rusin <zackr@vmware.com> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Javier Martinez Canillas <javierm@redhat.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Helge Deller <deller@gmx.de> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Zhen Lei <thunder.leizhen@huawei.com> Cc: Changcheng Deng <deng.changcheng@zte.com.cn> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <mripard@kernel.org> Cc: dri-devel@lists.freedesktop.org Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-8-tzimmermann@suse.de --- drivers/video/aperture.c | 14 ++++++++++++++ drivers/video/fbdev/core/fbmem.c | 12 ------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c index f42a0d8bc211..101e13c2cf41 100644 --- a/drivers/video/aperture.c +++ b/drivers/video/aperture.c @@ -8,6 +8,7 @@ #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/sysfb.h> #include <linux/types.h> #include <linux/vgaarb.h> @@ -286,7 +287,20 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si #if IS_REACHABLE(CONFIG_FB) struct apertures_struct *a; int ret; +#endif + /* + * If a driver asked to unregister a platform device registered by + * sysfb, then can be assumed that this is a driver for a display + * that is set up by the system firmware and has a generic driver. + * + * Drivers for devices that don't have a generic driver will never + * ask for this, so let's assume that a real driver for the display + * was already probed and prevent sysfb to register devices later. + */ + sysfb_disable(); + +#if IS_REACHABLE(CONFIG_FB) a = alloc_apertures(1); if (!a) return -ENOMEM; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index c8f9532cc6b4..4ed0960e6c05 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -19,7 +19,6 @@ #include <linux/kernel.h> #include <linux/major.h> #include <linux/slab.h> -#include <linux/sysfb.h> #include <linux/mm.h> #include <linux/mman.h> #include <linux/vt.h> @@ -1777,17 +1776,6 @@ int remove_conflicting_framebuffers(struct apertures_struct *a, do_free = true; } - /* - * If a driver asked to unregister a platform device registered by - * sysfb, then can be assumed that this is a driver for a display - * that is set up by the system firmware and has a generic driver. - * - * Drivers for devices that don't have a generic driver will never - * ask for this, so let's assume that a real driver for the display - * was already probed and prevent sysfb to register devices later. - */ - sysfb_disable(); - mutex_lock(®istration_lock); do_remove_conflicting_framebuffers(a, name, primary); mutex_unlock(®istration_lock); From 4652905f4e30ab7b4827faa38343fdafa90f2956 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:19 +0200 Subject: [PATCH 160/396] video: Provide constants for VGA I/O range Provide VGA_FB_ constants for the VGA framebuffer I/O range and convert fbdev code. In the case of vga16fb, this is a rename of the existing constants VGA_FB_PHYS and VGA_FB_PHYS_LEN. v2: * clarify relationship with old constants in vga16fb (Javier) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-9-tzimmermann@suse.de --- drivers/video/fbdev/core/fbmem.c | 4 ++-- drivers/video/fbdev/vga16fb.c | 15 ++++++--------- include/video/vga.h | 2 ++ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 4ed0960e6c05..6b0d5edcdafb 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -39,6 +39,7 @@ #include <asm/fb.h> +#include <video/vga.h> /* * Frame buffer device initialization and setup routines @@ -1561,7 +1562,6 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, static void do_unregister_framebuffer(struct fb_info *fb_info); -#define VGA_FB_PHYS 0xA0000 static void do_remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary) { @@ -1580,7 +1580,7 @@ restart_removal: device = registered_fb[i]->device; if (fb_do_apertures_overlap(gen_aper, a) || (primary && gen_aper && gen_aper->count && - gen_aper->ranges[0].base == VGA_FB_PHYS)) { + gen_aper->ranges[0].base == VGA_FB_PHYS_BASE)) { printk(KERN_INFO "fb%d: switching to %s from %s\n", i, name, registered_fb[i]->fix.id); diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c index 3312b6a4e00d..35cf51ae3292 100644 --- a/drivers/video/fbdev/vga16fb.c +++ b/drivers/video/fbdev/vga16fb.c @@ -25,9 +25,6 @@ #include <asm/io.h> #include <video/vga.h> -#define VGA_FB_PHYS 0xA0000 -#define VGA_FB_PHYS_LEN 65536 - #define MODE_SKIP4 1 #define MODE_8BPP 2 #define MODE_CFB 4 @@ -87,8 +84,8 @@ static struct fb_var_screeninfo vga16fb_defined = { /* name should not depend on EGA/VGA */ static const struct fb_fix_screeninfo vga16fb_fix = { .id = "VGA16 VGA", - .smem_start = VGA_FB_PHYS, - .smem_len = VGA_FB_PHYS_LEN, + .smem_start = VGA_FB_PHYS_BASE, + .smem_len = VGA_FB_PHYS_SIZE, .type = FB_TYPE_VGA_PLANES, .type_aux = FB_AUX_VGA_PLANES_VGA4, .visual = FB_VISUAL_PSEUDOCOLOR, @@ -1333,8 +1330,8 @@ static int vga16fb_probe(struct platform_device *dev) goto err_ioremap; } - /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ - info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0); + /* XXX share VGA_FB_PHYS_BASE and I/O region with vgacon and others */ + info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS_BASE, 0); if (!info->screen_base) { printk(KERN_ERR "vga16fb: unable to map device\n"); @@ -1385,8 +1382,8 @@ static int vga16fb_probe(struct platform_device *dev) vga16fb_update_fix(info); - info->apertures->ranges[0].base = VGA_FB_PHYS; - info->apertures->ranges[0].size = VGA_FB_PHYS_LEN; + info->apertures->ranges[0].base = VGA_FB_PHYS_BASE; + info->apertures->ranges[0].size = VGA_FB_PHYS_SIZE; if (register_framebuffer(info) < 0) { printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); diff --git a/include/video/vga.h b/include/video/vga.h index ef8e9fa9b9bd..947c0abd04ef 100644 --- a/include/video/vga.h +++ b/include/video/vga.h @@ -22,6 +22,8 @@ #include <asm/vga.h> #include <asm/byteorder.h> +#define VGA_FB_PHYS_BASE 0xA0000 /* VGA framebuffer I/O base */ +#define VGA_FB_PHYS_SIZE 65536 /* VGA framebuffer I/O size */ /* Some of the code below is taken from SVGAlib. The original, unmodified copyright notice for that code is below. */ From 482b1c7d478875508ac112c36dcd65739f664b0e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:20 +0200 Subject: [PATCH 161/396] video/aperture: Remove conflicting VGA devices, if any On the primary graphics adapter, a driver might conflict with a VGA driver that controls the VGA framebuffer I/O range. Remove the VGA driver from the aperture helpers. Until now, this case has been hendled by fbdev, but it should work even with fbdev disabled. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-10-tzimmermann@suse.de --- drivers/video/aperture.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c index 101e13c2cf41..abc691284a77 100644 --- a/drivers/video/aperture.c +++ b/drivers/video/aperture.c @@ -12,6 +12,8 @@ #include <linux/types.h> #include <linux/vgaarb.h> +#include <video/vga.h> + /** * DOC: overview * @@ -300,6 +302,16 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si */ sysfb_disable(); + aperture_detach_devices(base, size); + + /* + * If this is the primary adapter, there could be a VGA device + * that consumes the VGA framebuffer I/O range. Remove this device + * as well. + */ + if (primary) + aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE); + #if IS_REACHABLE(CONFIG_FB) a = alloc_apertures(1); if (!a) @@ -315,8 +327,6 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si return ret; #endif - aperture_detach_devices(base, size); - return 0; } EXPORT_SYMBOL(aperture_remove_conflicting_devices); From 72a6a3e03bdc957996a74c1053eab1b2c073db8e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:21 +0200 Subject: [PATCH 162/396] fbdev: Acquire framebuffer apertures for firmware devices When registering a generic framebuffer, automatically acquire ownership of the framebuffer's I/O range. The device will now be handled by the aperture helpers. Fbdev-based conflict handling is no longer required. v2: * use fb_ prefix instead of fbm_ (Javier) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-11-tzimmermann@suse.de --- drivers/video/fbdev/core/fbmem.c | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 6b0d5edcdafb..d790d30624a8 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -13,6 +13,7 @@ #include <linux/module.h> +#include <linux/aperture.h> #include <linux/compat.h> #include <linux/types.h> #include <linux/errno.h> @@ -1751,6 +1752,32 @@ static void do_unregister_framebuffer(struct fb_info *fb_info) put_fb_info(fb_info); } +static int fb_aperture_acquire_for_platform_device(struct fb_info *fb_info) +{ + struct apertures_struct *ap = fb_info->apertures; + struct device *dev = fb_info->device; + struct platform_device *pdev; + unsigned int i; + int ret; + + if (!ap) + return 0; + + if (!dev_is_platform(dev)) + return 0; + + pdev = to_platform_device(dev); + + for (ret = 0, i = 0; i < ap->count; ++i) { + ret = devm_aperture_acquire_for_platform_device(pdev, ap->ranges[i].base, + ap->ranges[i].size); + if (ret) + break; + } + + return ret; +} + /** * remove_conflicting_framebuffers - remove firmware-configured framebuffers * @a: memory range, users of which are to be removed @@ -1801,6 +1828,12 @@ register_framebuffer(struct fb_info *fb_info) { int ret; + if (fb_info->flags & FBINFO_MISC_FIRMWARE) { + ret = fb_aperture_acquire_for_platform_device(fb_info); + if (ret) + return ret; + } + mutex_lock(®istration_lock); ret = do_register_framebuffer(fb_info); mutex_unlock(®istration_lock); From 15fced5b051e6e22c228a521a5894b12c2ba0892 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 18 Jul 2022 09:23:22 +0200 Subject: [PATCH 163/396] fbdev: Remove conflict-handling code Remove the call to do_remove_conflicting_framebuffers() from the framebuffer registration. Aperture helpers take care of removing conflicting devices. With all ownership information stored in the aperture datastrcutures, remove remove_conflicting_framebuffers() entirely. This change also rectifies DRM generic-framebuffer registration, which tried to unregister conflicting framebuffers, even though it's entirely build on top of DRM. v2: * remove internal aperture-overlap helpers, which are now unused Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-12-tzimmermann@suse.de --- drivers/video/aperture.c | 21 ----- drivers/video/fbdev/core/fbmem.c | 136 ------------------------------- include/linux/fb.h | 2 - 3 files changed, 159 deletions(-) diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c index abc691284a77..9e6bcc03a1a4 100644 --- a/drivers/video/aperture.c +++ b/drivers/video/aperture.c @@ -2,7 +2,6 @@ #include <linux/aperture.h> #include <linux/device.h> -#include <linux/fb.h> /* for old fbdev helpers */ #include <linux/list.h> #include <linux/mutex.h> #include <linux/pci.h> @@ -286,11 +285,6 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size) int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, bool primary, const char *name) { -#if IS_REACHABLE(CONFIG_FB) - struct apertures_struct *a; - int ret; -#endif - /* * If a driver asked to unregister a platform device registered by * sysfb, then can be assumed that this is a driver for a display @@ -312,21 +306,6 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si if (primary) aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE); -#if IS_REACHABLE(CONFIG_FB) - a = alloc_apertures(1); - if (!a) - return -ENOMEM; - - a->ranges[0].base = base; - a->ranges[0].size = size; - - ret = remove_conflicting_framebuffers(a, name, primary); - kfree(a); - - if (ret) - return ret; -#endif - return 0; } EXPORT_SYMBOL(aperture_remove_conflicting_devices); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index d790d30624a8..6ae1c5fa19f9 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1526,102 +1526,6 @@ static int fb_check_foreignness(struct fb_info *fi) return 0; } -static bool apertures_overlap(struct aperture *gen, struct aperture *hw) -{ - /* is the generic aperture base the same as the HW one */ - if (gen->base == hw->base) - return true; - /* is the generic aperture base inside the hw base->hw base+size */ - if (gen->base > hw->base && gen->base < hw->base + hw->size) - return true; - return false; -} - -static bool fb_do_apertures_overlap(struct apertures_struct *gena, - struct apertures_struct *hwa) -{ - int i, j; - if (!hwa || !gena) - return false; - - for (i = 0; i < hwa->count; ++i) { - struct aperture *h = &hwa->ranges[i]; - for (j = 0; j < gena->count; ++j) { - struct aperture *g = &gena->ranges[j]; - printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n", - (unsigned long long)g->base, - (unsigned long long)g->size, - (unsigned long long)h->base, - (unsigned long long)h->size); - if (apertures_overlap(g, h)) - return true; - } - } - - return false; -} - -static void do_unregister_framebuffer(struct fb_info *fb_info); - -static void do_remove_conflicting_framebuffers(struct apertures_struct *a, - const char *name, bool primary) -{ - int i; - -restart_removal: - /* check all firmware fbs and kick off if the base addr overlaps */ - for_each_registered_fb(i) { - struct apertures_struct *gen_aper; - struct device *device; - - if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) - continue; - - gen_aper = registered_fb[i]->apertures; - device = registered_fb[i]->device; - if (fb_do_apertures_overlap(gen_aper, a) || - (primary && gen_aper && gen_aper->count && - gen_aper->ranges[0].base == VGA_FB_PHYS_BASE)) { - - printk(KERN_INFO "fb%d: switching to %s from %s\n", - i, name, registered_fb[i]->fix.id); - - /* - * If we kick-out a firmware driver, we also want to remove - * the underlying platform device, such as simple-framebuffer, - * VESA, EFI, etc. A native driver will then be able to - * allocate the memory range. - * - * If it's not a platform device, at least print a warning. A - * fix would add code to remove the device from the system. For - * framebuffers without any Linux device, print a warning as - * well. - */ - if (!device) { - pr_warn("fb%d: no device set\n", i); - do_unregister_framebuffer(registered_fb[i]); - } else if (dev_is_platform(device)) { - /* - * Drop the lock because if the device is unregistered, its - * driver will call to unregister_framebuffer(), that takes - * this lock. - */ - mutex_unlock(®istration_lock); - platform_device_unregister(to_platform_device(device)); - mutex_lock(®istration_lock); - } else { - pr_warn("fb%d: cannot remove device\n", i); - do_unregister_framebuffer(registered_fb[i]); - } - /* - * Restart the removal loop now that the device has been - * unregistered and its associated framebuffer gone. - */ - goto restart_removal; - } - } -} - static int do_register_framebuffer(struct fb_info *fb_info) { int i; @@ -1630,10 +1534,6 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (fb_check_foreignness(fb_info)) return -ENOSYS; - do_remove_conflicting_framebuffers(fb_info->apertures, - fb_info->fix.id, - fb_is_primary_device(fb_info)); - if (num_registered_fb == FB_MAX) return -ENXIO; @@ -1778,42 +1678,6 @@ static int fb_aperture_acquire_for_platform_device(struct fb_info *fb_info) return ret; } -/** - * remove_conflicting_framebuffers - remove firmware-configured framebuffers - * @a: memory range, users of which are to be removed - * @name: requesting driver name - * @primary: also kick vga16fb if present - * - * This function removes framebuffer devices (initialized by firmware/bootloader) - * which use memory range described by @a. If @a is NULL all such devices are - * removed. - */ -int remove_conflicting_framebuffers(struct apertures_struct *a, - const char *name, bool primary) -{ - bool do_free = false; - - if (!a) { - a = alloc_apertures(1); - if (!a) - return -ENOMEM; - - a->ranges[0].base = 0; - a->ranges[0].size = ~0; - do_free = true; - } - - mutex_lock(®istration_lock); - do_remove_conflicting_framebuffers(a, name, primary); - mutex_unlock(®istration_lock); - - if (do_free) - kfree(a); - - return 0; -} -EXPORT_SYMBOL(remove_conflicting_framebuffers); - /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure diff --git a/include/linux/fb.h b/include/linux/fb.h index b91c77016560..453c3b2b6b8e 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -615,8 +615,6 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern void unregister_framebuffer(struct fb_info *fb_info); -extern int remove_conflicting_framebuffers(struct apertures_struct *a, - const char *name, bool primary); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); From 64b88afbd92fbf434759d1896a7cf705e1c00e79 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:18 +0300 Subject: [PATCH 164/396] drm/virtio: Correct drm_gem_shmem_get_sg_table() error handling Previous commit fixed checking of the ERR_PTR value returned by drm_gem_shmem_get_sg_table(), but it missed to zero out the shmem->pages, which will crash virtio_gpu_cleanup_object(). Add the missing zeroing of the shmem->pages. Fixes: c24968734abf ("drm/virtio: Fix NULL vs IS_ERR checking in virtio_gpu_object_shmem_init") Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-2-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_object.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 1cc8f3fc8e4b..87b19b3b96e0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -170,6 +170,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, shmem->pages = drm_gem_shmem_get_sg_table(&bo->base); if (IS_ERR(shmem->pages)) { drm_gem_shmem_unpin(&bo->base); + shmem->pages = NULL; return PTR_ERR(shmem->pages); } From e473216b42aa1fd9fc6b94b608b42c210c655908 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:19 +0300 Subject: [PATCH 165/396] drm/virtio: Check whether transferred 2D BO is shmem Transferred 2D BO always must be a shmem BO. Add check for that to prevent NULL dereference if userspace passes a VRAM BO. Cc: stable@vger.kernel.org Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-3-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_vq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index b7529b2b9883..1262fd0b3bef 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -597,7 +597,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo); - if (use_dma_api) + if (virtio_gpu_is_shmem(bo) && use_dma_api) dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, shmem->pages, DMA_TO_DEVICE); From fdf0ff4d12cbcd76b53f27c96ce51ddca400884a Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:20 +0300 Subject: [PATCH 166/396] drm/virtio: Unlock reservations on virtio_gpu_object_shmem_init() error Unlock reservations in the error code path of virtio_gpu_object_create() to silence debug warning splat produced by ww_mutex_destroy(&obj->lock) when GEM is released with the held lock. Cc: stable@vger.kernel.org Fixes: 30172efbfb84 ("drm/virtio: blob prep: refactor getting pages and attaching backing") Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-4-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_object.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 87b19b3b96e0..75a159df0af6 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -249,6 +249,8 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents, &nents); if (ret != 0) { + if (fence) + virtio_gpu_array_unlock_resv(objs); virtio_gpu_array_put_free(objs); virtio_gpu_free_object(&shmem_obj->base); return ret; From 0f877398d30e1df657a31a62f7c7de1869b072b5 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:21 +0300 Subject: [PATCH 167/396] drm/virtio: Unlock reservations on dma_resv_reserve_fences() error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlock reservations on dma_resv_reserve_fences() error to fix recursive locking of the reservations when this error happens. Cc: stable@vger.kernel.org Fixes: c8d4c18bfbc4 ("dma-buf/drivers: make reserving a shared slot mandatory v4") Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-5-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_gem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index 580a78809836..7db48d17ee3a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -228,8 +228,10 @@ int virtio_gpu_array_lock_resv(struct virtio_gpu_object_array *objs) for (i = 0; i < objs->nents; ++i) { ret = dma_resv_reserve_fences(objs->objs[i]->resv, 1); - if (ret) + if (ret) { + virtio_gpu_array_unlock_resv(objs); return ret; + } } return ret; } From 4656b3a26a9e9fe5f04bfd2ab55b066266ba7f4d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:22 +0300 Subject: [PATCH 168/396] drm/virtio: Use appropriate atomic state in virtio_gpu_plane_cleanup_fb() Make virtio_gpu_plane_cleanup_fb() to clean the state which DRM core wants to clean up and not the current plane's state. Normally the older atomic state is cleaned up, but the newer state could also be cleaned up in case of aborted commits. Cc: stable@vger.kernel.org Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-6-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_plane.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 6d3cc9e238a4..7148f3813d8b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -266,14 +266,14 @@ static int virtio_gpu_plane_prepare_fb(struct drm_plane *plane, } static void virtio_gpu_plane_cleanup_fb(struct drm_plane *plane, - struct drm_plane_state *old_state) + struct drm_plane_state *state) { struct virtio_gpu_framebuffer *vgfb; - if (!plane->state->fb) + if (!state->fb) return; - vgfb = to_virtio_gpu_framebuffer(plane->state->fb); + vgfb = to_virtio_gpu_framebuffer(state->fb); if (vgfb->fence) { dma_fence_put(&vgfb->fence->f); vgfb->fence = NULL; From e7fef092330321ff311e8c06338ce1b4b608ba05 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:23 +0300 Subject: [PATCH 169/396] drm/virtio: Simplify error handling of virtio_gpu_object_create() Change the order of SHMEM initialization and reservation locking to make code cleaner and to prepare for transitioning of the common GEM SHMEM code to use the GEM's reservation lock instead of the shmem.page_lock. There is no need to lock reservation during allocation of the SHMEM pages because the lock is needed only to avoid racing with the async host-side allocation. Hence we can safely move the SHMEM initialization out of the reservation lock. Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-7-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_object.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 75a159df0af6..62b4d075cfac 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -235,6 +235,10 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, bo->dumb = params->dumb; + ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents, &nents); + if (ret != 0) + goto err_put_id; + if (fence) { ret = -ENOMEM; objs = virtio_gpu_array_alloc(1); @@ -247,15 +251,6 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, goto err_put_objs; } - ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents, &nents); - if (ret != 0) { - if (fence) - virtio_gpu_array_unlock_resv(objs); - virtio_gpu_array_put_free(objs); - virtio_gpu_free_object(&shmem_obj->base); - return ret; - } - if (params->blob) { if (params->blob_mem == VIRTGPU_BLOB_MEM_GUEST) bo->guest_blob = true; From b5c9ed70d1a94c59dad7b1ecfc928863c0fe6ac0 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:24 +0300 Subject: [PATCH 170/396] drm/virtio: Improve DMA API usage for shmem BOs DRM API requires the DRM's driver to be backed with the device that can be used for generic DMA operations. The VirtIO-GPU device can't perform DMA operations if it uses PCI transport because PCI device driver creates a virtual VirtIO-GPU device that isn't associated with the PCI. Use PCI's GPU device for the DRM's device instead of the VirtIO-GPU device and drop DMA-related hacks from the VirtIO-GPU driver. Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-8-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_drv.c | 51 ++++++----------------- drivers/gpu/drm/virtio/virtgpu_drv.h | 5 +-- drivers/gpu/drm/virtio/virtgpu_kms.c | 7 ++-- drivers/gpu/drm/virtio/virtgpu_object.c | 55 +++++-------------------- drivers/gpu/drm/virtio/virtgpu_vq.c | 13 +++--- 5 files changed, 32 insertions(+), 99 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 5f25a8d15464..0141b7df97ec 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -46,12 +46,11 @@ static int virtio_gpu_modeset = -1; MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); module_param_named(modeset, virtio_gpu_modeset, int, 0400); -static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vdev) +static int virtio_gpu_pci_quirk(struct drm_device *dev) { - struct pci_dev *pdev = to_pci_dev(vdev->dev.parent); + struct pci_dev *pdev = to_pci_dev(dev->dev); const char *pname = dev_name(&pdev->dev); bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA; - char unique[20]; int ret; DRM_INFO("pci: %s detected at %s\n", @@ -63,39 +62,7 @@ static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vd return ret; } - /* - * Normally the drm_dev_set_unique() call is done by core DRM. - * The following comment covers, why virtio cannot rely on it. - * - * Unlike the other virtual GPU drivers, virtio abstracts the - * underlying bus type by using struct virtio_device. - * - * Hence the dev_is_pci() check, used in core DRM, will fail - * and the unique returned will be the virtio_device "virtio0", - * while a "pci:..." one is required. - * - * A few other ideas were considered: - * - Extend the dev_is_pci() check [in drm_set_busid] to - * consider virtio. - * Seems like a bigger hack than what we have already. - * - * - Point drm_device::dev to the parent of the virtio_device - * Semantic changes: - * * Using the wrong device for i2c, framebuffer_alloc and - * prime import. - * Visual changes: - * * Helpers such as DRM_DEV_ERROR, dev_info, drm_printer, - * will print the wrong information. - * - * We could address the latter issues, by introducing - * drm_device::bus_dev, ... which would be used solely for this. - * - * So for the moment keep things as-is, with a bulky comment - * for the next person who feels like removing this - * drm_dev_set_unique() quirk. - */ - snprintf(unique, sizeof(unique), "pci:%s", pname); - return drm_dev_set_unique(dev, unique); + return 0; } static int virtio_gpu_probe(struct virtio_device *vdev) @@ -109,18 +76,24 @@ static int virtio_gpu_probe(struct virtio_device *vdev) if (virtio_gpu_modeset == 0) return -EINVAL; - dev = drm_dev_alloc(&driver, &vdev->dev); + /* + * The virtio-gpu device is a virtual device that doesn't have DMA + * ops assigned to it, nor DMA mask set and etc. Its parent device + * is actual GPU device we want to use it for the DRM's device in + * order to benefit from using generic DRM APIs. + */ + dev = drm_dev_alloc(&driver, vdev->dev.parent); if (IS_ERR(dev)) return PTR_ERR(dev); vdev->priv = dev; if (!strcmp(vdev->dev.parent->bus->name, "pci")) { - ret = virtio_gpu_pci_quirk(dev, vdev); + ret = virtio_gpu_pci_quirk(dev); if (ret) goto err_free; } - ret = virtio_gpu_init(dev); + ret = virtio_gpu_init(vdev, dev); if (ret) goto err_free; diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index f80664cf98d0..9b98470593b0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -101,8 +101,6 @@ struct virtio_gpu_object { struct virtio_gpu_object_shmem { struct virtio_gpu_object base; - struct sg_table *pages; - uint32_t mapped; }; struct virtio_gpu_object_vram { @@ -215,7 +213,6 @@ struct virtio_gpu_drv_cap_cache { }; struct virtio_gpu_device { - struct device *dev; struct drm_device *ddev; struct virtio_device *vdev; @@ -283,7 +280,7 @@ extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS]; void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file); /* virtgpu_kms.c */ -int virtio_gpu_init(struct drm_device *dev); +int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev); void virtio_gpu_deinit(struct drm_device *dev); void virtio_gpu_release(struct drm_device *dev); int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file); diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 3313b92db531..0d1e3eb61bee 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -110,7 +110,7 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev, vgdev->num_capsets = num_capsets; } -int virtio_gpu_init(struct drm_device *dev) +int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) { static vq_callback_t *callbacks[] = { virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack @@ -123,7 +123,7 @@ int virtio_gpu_init(struct drm_device *dev) u32 num_scanouts, num_capsets; int ret = 0; - if (!virtio_has_feature(dev_to_virtio(dev->dev), VIRTIO_F_VERSION_1)) + if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) return -ENODEV; vgdev = kzalloc(sizeof(struct virtio_gpu_device), GFP_KERNEL); @@ -132,8 +132,7 @@ int virtio_gpu_init(struct drm_device *dev) vgdev->ddev = dev; dev->dev_private = vgdev; - vgdev->vdev = dev_to_virtio(dev->dev); - vgdev->dev = dev->dev; + vgdev->vdev = vdev; spin_lock_init(&vgdev->display_info_lock); spin_lock_init(&vgdev->resource_export_lock); diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 62b4d075cfac..8d7728181de0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -67,21 +67,6 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo) virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle); if (virtio_gpu_is_shmem(bo)) { - struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo); - - if (shmem->pages) { - if (shmem->mapped) { - dma_unmap_sgtable(vgdev->vdev->dev.parent, - shmem->pages, DMA_TO_DEVICE, 0); - shmem->mapped = 0; - } - - sg_free_table(shmem->pages); - kfree(shmem->pages); - shmem->pages = NULL; - drm_gem_shmem_unpin(&bo->base); - } - drm_gem_shmem_free(&bo->base); } else if (virtio_gpu_is_vram(bo)) { struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo); @@ -153,36 +138,18 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, unsigned int *nents) { bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); - struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo); struct scatterlist *sg; - int si, ret; + struct sg_table *pages; + int si; - ret = drm_gem_shmem_pin(&bo->base); - if (ret < 0) - return -EINVAL; + pages = drm_gem_shmem_get_pages_sgt(&bo->base); + if (IS_ERR(pages)) + return PTR_ERR(pages); - /* - * virtio_gpu uses drm_gem_shmem_get_sg_table instead of - * drm_gem_shmem_get_pages_sgt because virtio has it's own set of - * dma-ops. This is discouraged for other drivers, but should be fine - * since virtio_gpu doesn't support dma-buf import from other devices. - */ - shmem->pages = drm_gem_shmem_get_sg_table(&bo->base); - if (IS_ERR(shmem->pages)) { - drm_gem_shmem_unpin(&bo->base); - shmem->pages = NULL; - return PTR_ERR(shmem->pages); - } - - if (use_dma_api) { - ret = dma_map_sgtable(vgdev->vdev->dev.parent, - shmem->pages, DMA_TO_DEVICE, 0); - if (ret) - return ret; - *nents = shmem->mapped = shmem->pages->nents; - } else { - *nents = shmem->pages->orig_nents; - } + if (use_dma_api) + *nents = pages->nents; + else + *nents = pages->orig_nents; *ents = kvmalloc_array(*nents, sizeof(struct virtio_gpu_mem_entry), @@ -193,13 +160,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, } if (use_dma_api) { - for_each_sgtable_dma_sg(shmem->pages, sg, si) { + for_each_sgtable_dma_sg(pages, sg, si) { (*ents)[si].addr = cpu_to_le64(sg_dma_address(sg)); (*ents)[si].length = cpu_to_le32(sg_dma_len(sg)); (*ents)[si].padding = 0; } } else { - for_each_sgtable_sg(shmem->pages, sg, si) { + for_each_sgtable_sg(pages, sg, si) { (*ents)[si].addr = cpu_to_le64(sg_phys(sg)); (*ents)[si].length = cpu_to_le32(sg->length); (*ents)[si].padding = 0; diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 1262fd0b3bef..ee84256946ab 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -595,11 +595,10 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, struct virtio_gpu_transfer_to_host_2d *cmd_p; struct virtio_gpu_vbuffer *vbuf; bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); - struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo); if (virtio_gpu_is_shmem(bo) && use_dma_api) - dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, - shmem->pages, DMA_TO_DEVICE); + dma_sync_sgtable_for_device(&vgdev->vdev->dev, + bo->base.sgt, DMA_TO_DEVICE); cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); memset(cmd_p, 0, sizeof(*cmd_p)); @@ -1019,11 +1018,9 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, struct virtio_gpu_vbuffer *vbuf; bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); - if (virtio_gpu_is_shmem(bo) && use_dma_api) { - struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo); - dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, - shmem->pages, DMA_TO_DEVICE); - } + if (virtio_gpu_is_shmem(bo) && use_dma_api) + dma_sync_sgtable_for_device(&vgdev->vdev->dev, + bo->base.sgt, DMA_TO_DEVICE); cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); memset(cmd_p, 0, sizeof(*cmd_p)); From a9d2e8b5f1e5caa3cb038d7bb7bab530bcce5af1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:25 +0300 Subject: [PATCH 171/396] drm/virtio: Use dev_is_pci() Use common dev_is_pci() helper to replace the strcmp("pci") used by driver. Suggested-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-9-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 0141b7df97ec..0035affc3e59 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -87,7 +87,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev) return PTR_ERR(dev); vdev->priv = dev; - if (!strcmp(vdev->dev.parent->bus->name, "pci")) { + if (dev_is_pci(vdev->dev.parent)) { ret = virtio_gpu_pci_quirk(dev); if (ret) goto err_free; From 4c703f5d6f776eaa6a98611c9b5dfe800fbeb0c8 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <dmitry.osipenko@collabora.com> Date: Thu, 30 Jun 2022 23:07:26 +0300 Subject: [PATCH 172/396] drm/virtio: Return proper error codes instead of -1 Don't return -1 in error cases, return proper error code. The returned error codes propagate to error messages and to userspace and it's always good to have a meaningful error number for debugging purposes. Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-10-dmitry.osipenko@collabora.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_vq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index ee84256946ab..9ff8660b50ad 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -322,7 +322,7 @@ static int virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, if (fence && vbuf->objs) virtio_gpu_array_unlock_resv(vbuf->objs); free_vbuf(vgdev, vbuf); - return -1; + return -ENODEV; } if (vgdev->has_indirect) @@ -386,7 +386,7 @@ static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, if (!sgt) { if (fence && vbuf->objs) virtio_gpu_array_unlock_resv(vbuf->objs); - return -1; + return -ENOMEM; } elemcnt += sg_ents; @@ -720,7 +720,7 @@ static int virtio_get_edid_block(void *data, u8 *buf, size_t start = block * EDID_LENGTH; if (start + len > le32_to_cpu(resp->size)) - return -1; + return -EINVAL; memcpy(buf, resp->edid + start, len); return 0; } From 7847628862a808ff3802df96f54e5eab3ff448b6 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Thu, 14 Jul 2022 15:00:27 +0200 Subject: [PATCH 173/396] drm/virtio: plane: use drm managed resources Use drm managed resource allocation (drmm_universal_plane_alloc()) in order to cleanup/simplify drm plane .destroy callback. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220714130028.2127858-2-dakr@redhat.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_plane.c | 30 +++++++------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 7148f3813d8b..6a62f327dc09 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -67,16 +67,10 @@ uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc) return format; } -static void virtio_gpu_plane_destroy(struct drm_plane *plane) -{ - drm_plane_cleanup(plane); - kfree(plane); -} - static const struct drm_plane_funcs virtio_gpu_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = virtio_gpu_plane_destroy, + .destroy = drm_plane_cleanup, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, @@ -379,11 +373,7 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane; const uint32_t *formats; - int ret, nformats; - - plane = kzalloc(sizeof(*plane), GFP_KERNEL); - if (!plane) - return ERR_PTR(-ENOMEM); + int nformats; if (type == DRM_PLANE_TYPE_CURSOR) { formats = virtio_gpu_cursor_formats; @@ -394,17 +384,13 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, nformats = ARRAY_SIZE(virtio_gpu_formats); funcs = &virtio_gpu_primary_helper_funcs; } - ret = drm_universal_plane_init(dev, plane, 1 << index, - &virtio_gpu_plane_funcs, - formats, nformats, - NULL, type, NULL); - if (ret) - goto err_plane_init; + + plane = drmm_universal_plane_alloc(dev, struct drm_plane, dev, + 1 << index, &virtio_gpu_plane_funcs, + formats, nformats, NULL, type, NULL); + if (IS_ERR(plane)) + return plane; drm_plane_helper_add(plane, funcs); return plane; - -err_plane_init: - kfree(plane); - return ERR_PTR(ret); } From 90caf42527a40d09e0eed9fcbca08d757f4fd493 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Thu, 14 Jul 2022 15:00:28 +0200 Subject: [PATCH 174/396] drm/virtio: kms: use drm managed resources Allocate driver structures with drm managed resource allocators in order to cleanup/simplify the drm driver .release callback. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220714130028.2127858-3-dakr@redhat.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_kms.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 0d1e3eb61bee..27b7f14dae89 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -28,6 +28,7 @@ #include <linux/virtio_ring.h> #include <drm/drm_file.h> +#include <drm/drm_managed.h> #include "virtgpu_drv.h" @@ -66,10 +67,11 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev, { int i, ret; bool invalid_capset_id = false; + struct drm_device *drm = vgdev->ddev; - vgdev->capsets = kcalloc(num_capsets, - sizeof(struct virtio_gpu_drv_capset), - GFP_KERNEL); + vgdev->capsets = drmm_kcalloc(drm, num_capsets, + sizeof(struct virtio_gpu_drv_capset), + GFP_KERNEL); if (!vgdev->capsets) { DRM_ERROR("failed to allocate cap sets\n"); return; @@ -94,7 +96,7 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev, if (ret == 0 || invalid_capset_id) { spin_lock(&vgdev->display_info_lock); - kfree(vgdev->capsets); + drmm_kfree(drm, vgdev->capsets); vgdev->capsets = NULL; spin_unlock(&vgdev->display_info_lock); return; @@ -126,7 +128,7 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) return -ENODEV; - vgdev = kzalloc(sizeof(struct virtio_gpu_device), GFP_KERNEL); + vgdev = drmm_kzalloc(dev, sizeof(struct virtio_gpu_device), GFP_KERNEL); if (!vgdev) return -ENOMEM; @@ -256,7 +258,6 @@ err_vbufs: vgdev->vdev->config->del_vqs(vgdev->vdev); err_vqs: dev->dev_private = NULL; - kfree(vgdev); return ret; } @@ -295,9 +296,6 @@ void virtio_gpu_release(struct drm_device *dev) if (vgdev->has_host_visible) drm_mm_takedown(&vgdev->host_visible_mm); - - kfree(vgdev->capsets); - kfree(vgdev); } int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file) From 8f48dbd6deaf5a14c924c1de08bf7e36526bf3e7 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Date: Sat, 18 Jun 2022 17:26:08 +0200 Subject: [PATCH 175/396] drm/bochs: Fix some error handling paths in bochs_pci_probe() The remove() function calls bochs_hw_fini() but this function is not called in the error handling of the probe. This call releases the resources allocated by bochs_hw_init() used in bochs_load(). Update the probe and bochs_load() to call bochs_hw_fini() if an error occurs after a successful bochs_hw_init() call. Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Link: http://patchwork.freedesktop.org/patch/msgid/0e676e4d56ab5b10fcf22860081414445611dfa7.1655565953.git.christophe.jaillet@wanadoo.fr Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/tiny/bochs.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c index 82364a0a7b18..08de13774862 100644 --- a/drivers/gpu/drm/tiny/bochs.c +++ b/drivers/gpu/drm/tiny/bochs.c @@ -583,13 +583,17 @@ static int bochs_load(struct drm_device *dev) ret = drmm_vram_helper_init(dev, bochs->fb_base, bochs->fb_size); if (ret) - return ret; + goto err_hw_fini; ret = bochs_kms_init(bochs); if (ret) - return ret; + goto err_hw_fini; return 0; + +err_hw_fini: + bochs_hw_fini(dev); + return ret; } DEFINE_DRM_GEM_FOPS(bochs_fops); @@ -664,11 +668,13 @@ static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent ret = drm_dev_register(dev, 0); if (ret) - goto err_free_dev; + goto err_hw_fini; drm_fbdev_generic_setup(dev, 32); return ret; +err_hw_fini: + bochs_hw_fini(dev); err_free_dev: drm_dev_put(dev); return ret; From 1d43a5120ab49f22ba6c5901ad3994e254510303 Mon Sep 17 00:00:00 2001 From: Liang He <windhl@126.com> Date: Tue, 19 Jul 2022 14:54:46 +0800 Subject: [PATCH 176/396] drm/bridge: anx7625: Fix refcount bug in anx7625_parse_dt() In anx7625_parse_dt(), 'pdata->mipi_host_node' will be assigned a new reference with of_graph_get_remote_node() which will increase the refcount of the object, correspondingly, we should call of_node_put() for the old reference stored in the 'pdata->mipi_host_node'. Fixes: 8bdfc5dae4e3 ("drm/bridge: anx7625: Add anx7625 MIPI DSI/DPI to DP") Signed-off-by: Liang He <windhl@126.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220719065447.1080817-1-windhl@126.com --- drivers/gpu/drm/bridge/analogix/anx7625.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index d1f1d525aeb6..79fc7a50b497 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1642,6 +1642,7 @@ static int anx7625_parse_dt(struct device *dev, anx7625_get_swing_setting(dev, pdata); pdata->is_dpi = 0; /* default dsi mode */ + of_node_put(pdata->mipi_host_node); pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0); if (!pdata->mipi_host_node) { DRM_DEV_ERROR(dev, "fail to get internal panel.\n"); From 14e7157afb055248ed34901fcd6fbf54201cfea1 Mon Sep 17 00:00:00 2001 From: Liang He <windhl@126.com> Date: Tue, 19 Jul 2022 14:54:47 +0800 Subject: [PATCH 177/396] drm/bridge: tc358767: Add of_node_put() when breaking out of loop In tc_probe_bridge_endpoint(), we should call of_node_put() when breaking out of the for_each_endpoint_of_node() which will automatically increase and decrease the refcount. Fixes: 71f7d9c03118 ("drm/bridge: tc358767: Detect bridge mode from connected endpoints in DT") Signed-off-by: Liang He <windhl@126.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220719065447.1080817-2-windhl@126.com --- drivers/gpu/drm/bridge/tc358767.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 02bd757a8987..1dc107f13645 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -2010,9 +2010,10 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc) for_each_endpoint_of_node(dev->of_node, node) { of_graph_parse_endpoint(node, &endpoint); - if (endpoint.port > 2) + if (endpoint.port > 2) { + of_node_put(node); return -EINVAL; - + } mode |= BIT(endpoint.port); } From 4d9db10576ff51afa8cf7727fbad55ada299359b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:21:08 +0200 Subject: [PATCH 178/396] drm/format-helper: Fix endianness in drm_fb_*_to_*() conversion helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRM formats are defined to be little-endian, unless the DRM_FORMAT_BIG_ENDIAN flag is set. Hence when converting from one format to another, multi-byte pixel values loaded from memory must be converted from little-endian to host-endian. Conversely, multi-byte pixel values written to memory must be converted from host-endian to little-endian. Currently only drm_fb_xrgb8888_to_rgb332_line() includes endianness handling. Fix this by adding endianness handling to all conversion functions that process multi-byte pixel values. Note that the conversion to RGB565 is special, as there are two versions: with and without byteswapping of the RGB565 pixel data. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Link: https://patchwork.freedesktop.org/patch/msgid/33f390d3bae2c5a45c0050097dc95f2e17644f2f.1657300532.git.geert@linux-m68k.org --- drivers/gpu/drm/drm_format_helper.c | 80 +++++++++++++++++------------ 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index a3ccd8bc966f..c6182b5de78b 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -279,14 +279,16 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels) { u16 *dbuf16 = dbuf; - const u32 *sbuf32 = sbuf; + const __le32 *sbuf32 = sbuf; unsigned int x; u16 val16; + u32 pix; for (x = 0; x < pixels; x++) { - val16 = ((sbuf32[x] & 0x00F80000) >> 8) | - ((sbuf32[x] & 0x0000FC00) >> 5) | - ((sbuf32[x] & 0x000000F8) >> 3); + pix = le32_to_cpu(sbuf32[x]); + val16 = ((pix & 0x00F80000) >> 8) | + ((pix & 0x0000FC00) >> 5) | + ((pix & 0x000000F8) >> 3); dbuf16[x] = val16; } } @@ -295,14 +297,16 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, unsigned int pixels) { u16 *dbuf16 = dbuf; - const u32 *sbuf32 = sbuf; + const __le32 *sbuf32 = sbuf; unsigned int x; u16 val16; + u32 pix; for (x = 0; x < pixels; x++) { - val16 = ((sbuf32[x] & 0x00F80000) >> 8) | - ((sbuf32[x] & 0x0000FC00) >> 5) | - ((sbuf32[x] & 0x000000F8) >> 3); + pix = le32_to_cpu(sbuf32[x]); + val16 = ((pix & 0x00F80000) >> 8) | + ((pix & 0x0000FC00) >> 5) | + ((pix & 0x000000F8) >> 3); dbuf16[x] = swab16(val16); } } @@ -360,13 +364,15 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_toio); static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels) { u8 *dbuf8 = dbuf; - const u32 *sbuf32 = sbuf; + const __le32 *sbuf32 = sbuf; unsigned int x; + u32 pix; for (x = 0; x < pixels; x++) { - *dbuf8++ = (sbuf32[x] & 0x000000FF) >> 0; - *dbuf8++ = (sbuf32[x] & 0x0000FF00) >> 8; - *dbuf8++ = (sbuf32[x] & 0x00FF0000) >> 16; + pix = le32_to_cpu(sbuf32[x]); + *dbuf8++ = (pix & 0x000000FF) >> 0; + *dbuf8++ = (pix & 0x0000FF00) >> 8; + *dbuf8++ = (pix & 0x00FF0000) >> 16; } } @@ -410,17 +416,19 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio); static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { - u32 *dbuf32 = dbuf; - const u16 *sbuf16 = sbuf; + __le32 *dbuf32 = dbuf; + const __le16 *sbuf16 = sbuf; unsigned int x; - for (x = 0; x < pixels; x++, ++sbuf16, ++dbuf32) { - u32 val32 = ((*sbuf16 & 0xf800) << 8) | - ((*sbuf16 & 0x07e0) << 5) | - ((*sbuf16 & 0x001f) << 3); - *dbuf32 = 0xff000000 | val32 | - ((val32 >> 3) & 0x00070007) | - ((val32 >> 2) & 0x00000300); + for (x = 0; x < pixels; x++) { + u16 val16 = le16_to_cpu(sbuf16[x]); + u32 val32 = ((val16 & 0xf800) << 8) | + ((val16 & 0x07e0) << 5) | + ((val16 & 0x001f) << 3); + val32 = 0xff000000 | val32 | + ((val32 >> 3) & 0x00070007) | + ((val32 >> 2) & 0x00000300); + dbuf32[x] = cpu_to_le32(val32); } } @@ -434,7 +442,7 @@ static void drm_fb_rgb565_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_p static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { - u32 *dbuf32 = dbuf; + __le32 *dbuf32 = dbuf; const u8 *sbuf8 = sbuf; unsigned int x; @@ -442,7 +450,8 @@ static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne u8 r = *sbuf8++; u8 g = *sbuf8++; u8 b = *sbuf8++; - *dbuf32++ = 0xff000000 | (r << 16) | (g << 8) | b; + u32 pix = 0xff000000 | (r << 16) | (g << 8) | b; + dbuf32[x] = cpu_to_le32(pix); } } @@ -456,16 +465,19 @@ static void drm_fb_rgb888_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_p static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) { - u32 *dbuf32 = dbuf; - const u32 *sbuf32 = sbuf; + __le32 *dbuf32 = dbuf; + const __le32 *sbuf32 = sbuf; unsigned int x; u32 val32; + u32 pix; for (x = 0; x < pixels; x++) { - val32 = ((sbuf32[x] & 0x000000FF) << 2) | - ((sbuf32[x] & 0x0000FF00) << 4) | - ((sbuf32[x] & 0x00FF0000) << 6); - *dbuf32++ = val32 | ((val32 >> 8) & 0x00300C03); + pix = le32_to_cpu(sbuf32[x]); + val32 = ((pix & 0x000000FF) << 2) | + ((pix & 0x0000FF00) << 4) | + ((pix & 0x00FF0000) << 6); + pix = val32 | ((val32 >> 8) & 0x00300C03); + *dbuf32++ = cpu_to_le32(pix); } } @@ -494,17 +506,17 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio); static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) { u8 *dbuf8 = dbuf; - const u32 *sbuf32 = sbuf; + const __le32 *sbuf32 = sbuf; unsigned int x; for (x = 0; x < pixels; x++) { - u8 r = (*sbuf32 & 0x00ff0000) >> 16; - u8 g = (*sbuf32 & 0x0000ff00) >> 8; - u8 b = *sbuf32 & 0x000000ff; + u32 pix = le32_to_cpu(sbuf32[x]); + u8 r = (pix & 0x00ff0000) >> 16; + u8 g = (pix & 0x0000ff00) >> 8; + u8 b = pix & 0x000000ff; /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */ *dbuf8++ = (3 * r + 6 * g + b) / 10; - sbuf32++; } } From fa2a87e4c5cea2beba9deabcbaf54d1979fff419 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven <geert@linux-m68k.org> Date: Fri, 8 Jul 2022 20:21:09 +0200 Subject: [PATCH 179/396] drm/gud: Fix endianness in gud_xrgb8888_to_color() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRM formats are defined to be little-endian, unless the DRM_FORMAT_BIG_ENDIAN flag is set. Hence when converting from one format to another, multi-byte pixel values loaded from memory must be converted from little-endian to host-endian. Conversely, multi-byte pixel values written to memory must be converted from host-endian to little-endian. Currently only drm_fb_xrgb8888_to_rgb332_line() includes endianness handling. Fix gud_xrgb8888_to_color() on big-endian platforms by adding the missing endianness handling. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Link: https://patchwork.freedesktop.org/patch/msgid/b47589ed5d8ca44e0956684412e3f16f3227f887.1657300532.git.geert@linux-m68k.org --- drivers/gpu/drm/gud/gud_pipe.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 4873f9799f41..d42592f6daab 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -105,7 +105,8 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma unsigned int bits_per_pixel = 8 / block_width; u8 r, g, b, pix, *block = dst; /* Assign to silence compiler warning */ unsigned int x, y, width; - u32 *pix32; + __le32 *sbuf32; + u32 pix32; size_t len; /* Start on a byte boundary */ @@ -114,8 +115,8 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma len = drm_format_info_min_pitch(format, 0, width) * drm_rect_height(rect); for (y = rect->y1; y < rect->y2; y++) { - pix32 = src + (y * fb->pitches[0]); - pix32 += rect->x1; + sbuf32 = src + (y * fb->pitches[0]); + sbuf32 += rect->x1; for (x = 0; x < width; x++) { unsigned int pixpos = x % block_width; /* within byte from the left */ @@ -126,9 +127,10 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma *block = 0; } - r = *pix32 >> 16; - g = *pix32 >> 8; - b = *pix32++; + pix32 = le32_to_cpu(*sbuf32++); + r = pix32 >> 16; + g = pix32 >> 8; + b = pix32; switch (format->format) { case GUD_DRM_FORMAT_XRGB1111: From 6d602e031103fb78dbe50dbf57a5f29737494c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Wed, 13 Jul 2022 18:14:52 +0200 Subject: [PATCH 180/396] drm/sched: move calling drm_sched_entity_select_rq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already discussed that the call to drm_sched_entity_select_rq() needs to move to drm_sched_job_arm() to be able to set a new scheduler list between _init() and _arm(). This was just not applied for some reason. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220714103902.7084-2-christian.koenig@amd.com --- drivers/gpu/drm/scheduler/sched_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 68317d3a7a27..e0ab14e0fb6b 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -592,7 +592,6 @@ int drm_sched_job_init(struct drm_sched_job *job, struct drm_sched_entity *entity, void *owner) { - drm_sched_entity_select_rq(entity); if (!entity->rq) return -ENOENT; @@ -628,7 +627,7 @@ void drm_sched_job_arm(struct drm_sched_job *job) struct drm_sched_entity *entity = job->entity; BUG_ON(!entity); - + drm_sched_entity_select_rq(entity); sched = entity->rq->sched; job->sched = sched; From 2dbeef82d14fda3b15d40c94522bdf83f9c33ae8 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Date: Mon, 11 Jul 2022 12:21:16 +0300 Subject: [PATCH 181/396] drm/bridge: ti-sn65dsi86: fetch bpc using drm_atomic_state Rather than reading the pdata->connector directly, fetch the connector using drm_atomic_state. This allows us to make pdata->connector optional (and thus supporting DRM_BRIDGE_ATTACH_NO_CONNECTOR). Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Tested-by: Steev Klimaszewski <steev@kali.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Tested-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220711092117.360797-2-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index d6dd4d99a229..b362a7bf4d97 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -779,9 +779,9 @@ static void ti_sn_bridge_set_dsi_rate(struct ti_sn65dsi86 *pdata) regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val); } -static unsigned int ti_sn_bridge_get_bpp(struct ti_sn65dsi86 *pdata) +static unsigned int ti_sn_bridge_get_bpp(struct drm_connector *connector) { - if (pdata->connector->display_info.bpc <= 6) + if (connector->display_info.bpc <= 6) return 18; else return 24; @@ -796,7 +796,7 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = { 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400 }; -static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata) +static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata, unsigned int bpp) { unsigned int bit_rate_khz, dp_rate_mhz; unsigned int i; @@ -804,7 +804,7 @@ static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata) &pdata->bridge.encoder->crtc->state->adjusted_mode; /* Calculate minimum bit rate based on our pixel clock. */ - bit_rate_khz = mode->clock * ti_sn_bridge_get_bpp(pdata); + bit_rate_khz = mode->clock * bpp; /* Calculate minimum DP data rate, taking 80% as per DP spec */ dp_rate_mhz = DIV_ROUND_UP(bit_rate_khz * DP_CLK_FUDGE_NUM, @@ -1016,12 +1016,21 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + struct drm_connector *connector; const char *last_err_str = "No supported DP rate"; unsigned int valid_rates; int dp_rate_idx; unsigned int val; int ret = -EINVAL; int max_dp_lanes; + unsigned int bpp; + + connector = drm_atomic_get_new_connector_for_encoder(old_bridge_state->base.state, + bridge->encoder); + if (!connector) { + dev_err_ratelimited(pdata->dev, "Could not get the connector\n"); + return; + } max_dp_lanes = ti_sn_get_max_lanes(pdata); pdata->dp_lanes = min(pdata->dp_lanes, max_dp_lanes); @@ -1047,8 +1056,9 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge, drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET, DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); + bpp = ti_sn_bridge_get_bpp(connector); /* Set the DP output format (18 bpp or 24 bpp) */ - val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0; + val = bpp == 18 ? BPP_18_RGB : 0; regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val); /* DP lane config */ @@ -1059,7 +1069,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge, valid_rates = ti_sn_bridge_read_valid_rates(pdata); /* Train until we run out of rates */ - for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata); + for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata, bpp); dp_rate_idx < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut); dp_rate_idx++) { if (!(valid_rates & BIT(dp_rate_idx))) From 6e2dc7ac71411eaf6363d63c333519e1d353d6b0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Date: Mon, 11 Jul 2022 12:21:17 +0300 Subject: [PATCH 182/396] drm/bridge: ti-sn65dsi86: support DRM_BRIDGE_ATTACH_NO_CONNECTOR Now as the driver does not depend on pdata->connector, add support for attaching the bridge with DRM_BRIDGE_ATTACH_NO_CONNECTOR. Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Tested-by: Steev Klimaszewski <steev@kali.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Tested-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220711092117.360797-3-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index b362a7bf4d97..369bf72717f6 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -698,11 +698,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); int ret; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } - pdata->aux.drm_dev = bridge->dev; ret = drm_dp_aux_register(&pdata->aux); if (ret < 0) { @@ -710,15 +705,18 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, return ret; } - /* We never want the next bridge to *also* create a connector: */ - flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR; - - /* Attach the next bridge */ + /* + * Attach the next bridge. + * We never want the next bridge to *also* create a connector. + */ ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge, - &pdata->bridge, flags); + &pdata->bridge, flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret < 0) goto err_initted_aux; + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + return 0; + pdata->connector = drm_bridge_connector_init(pdata->bridge.dev, pdata->bridge.encoder); if (IS_ERR(pdata->connector)) { From f6ff4570e567b687b851a2cf52c7e300c399d925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= <nfraprado@collabora.com> Date: Tue, 19 Jul 2022 16:38:54 -0400 Subject: [PATCH 183/396] drm/panel-edp: Add panel entry for R140NWF5 RH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add panel identification entry for the IVO R140NWF5 RH (product ID: 0x057d) panel. Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220719203857.1488831-2-nfraprado@collabora.com --- drivers/gpu/drm/panel/panel-edp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 3626469c4cc2..675d793d925e 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1854,6 +1854,12 @@ static const struct panel_delay delay_100_500_e200 = { .enable = 200, }; +static const struct panel_delay delay_200_500_e200 = { + .hpd_absent = 200, + .unprepare = 500, + .enable = 200, +}; + #define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \ { \ .name = _name, \ @@ -1882,6 +1888,8 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"), + EDP_PANEL_ENTRY('I', 'V', 'O', 0x057d, &delay_200_500_e200, "R140NWF5 RH"), + EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"), EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"), From b68735e8ef58be6df7a6f511c60186e6051d9fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= <nfraprado@collabora.com> Date: Wed, 20 Jul 2022 15:11:58 -0400 Subject: [PATCH 184/396] drm/panel-edp: Add panel entry for B120XAN01.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add panel identification entry for the AUO B120XAN01.0 (product ID: 0x1062) panel. Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720191158.1590833-1-nfraprado@collabora.com --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 675d793d925e..e6645d6e9b59 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1876,6 +1876,7 @@ static const struct panel_delay delay_200_500_e200 = { * Sort first by vendor, then by product ID. */ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"), From ac991b874b098ecde2c5eb81da48d52b6b22851b Mon Sep 17 00:00:00 2001 From: Wang Jingjin <wangjingjin1@huawei.com> Date: Sat, 16 Jul 2022 10:07:41 +0800 Subject: [PATCH 185/396] drm/vc4: Add explicit declaration of 'drmm_of_get_bridge' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the error of implicit declaration of function 'drmm_of_get_bridge': drivers/gpu/drm/vc4/vc4_dpi.c:278:11: error: implicit declaration of function ‘drmm_of_get_bridge’; did you mean ‘devm_drm_of_get_bridge’? [-Werror=implicit-function-declaration] bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0); Fixes: 055af0235aef ("drm/vc4: dpi: Switch to drmm_of_get_bridge") Signed-off-by: Wang Jingjin <wangjingjin1@huawei.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220716020741.4124893-1-wangjingjin1@huawei.com --- include/drm/drm_bridge.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index dba5d81e3b4a..6b65b0dfb4fb 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -959,6 +959,14 @@ static inline struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, { return ERR_PTR(-ENODEV); } + +static inline struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, + struct device_node *node, + u32 port, + u32 endpoint) +{ + return ERR_PTR(-ENODEV); +} #endif #endif From 2b8428a10fd3763819eabf1acef6b5b2c7875520 Mon Sep 17 00:00:00 2001 From: Liu Zixian <liuzixian4@huawei.com> Date: Mon, 18 Jul 2022 09:53:57 +0800 Subject: [PATCH 186/396] drm: correct comments On failure, these functions return error pointer, not NULL. Signed-off-by: Liu Zixian <liuzixian4@huawei.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220718015357.1722-1-liuzixian4@huawei.com --- drivers/gpu/drm/drm_gem_shmem_helper.c | 2 +- include/drm/drm_gem_shmem_helper.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 8ad0e02991ca..05ca028dd152 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -662,7 +662,7 @@ EXPORT_SYMBOL(drm_gem_shmem_print_info); * drm_gem_shmem_get_pages_sgt() instead. * * Returns: - * A pointer to the scatter/gather table of pinned pages or NULL on failure. + * A pointer to the scatter/gather table of pinned pages or error pointer on failure. */ struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem) { diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem_helper.h index d0a57853c188..a2201b2488c5 100644 --- a/include/drm/drm_gem_shmem_helper.h +++ b/include/drm/drm_gem_shmem_helper.h @@ -210,7 +210,7 @@ static inline void drm_gem_shmem_object_unpin(struct drm_gem_object *obj) * use it as their &drm_gem_object_funcs.get_sg_table handler. * * Returns: - * A pointer to the scatter/gather table of pinned pages or NULL on failure. + * A pointer to the scatter/gather table of pinned pages or error pointer on failure. */ static inline struct sg_table *drm_gem_shmem_object_get_sg_table(struct drm_gem_object *obj) { From fc94224c2e0ae8d83ac511a3ef4962178505469d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai <wenst@chromium.org> Date: Thu, 21 Jul 2022 17:22:58 +0800 Subject: [PATCH 187/396] drm/bridge: parade-ps8640: Fix regulator supply order The datasheet says that VDD12 must be enabled and at full voltage before VDD33 is enabled. Reorder the bulk regulator supply names so that VDD12 is enabled before VDD33. Any enable ramp delays should be handled by setting proper constraints on the regulators. Fixes: bc1aee7fc8f0 ("drm/bridge: Add I2C based driver for ps8640 bridge") Signed-off-by: Chen-Yu Tsai <wenst@chromium.org> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220721092258.3397461-1-wenst@chromium.org --- drivers/gpu/drm/bridge/parade-ps8640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 31e88cb39f8a..49107a6cdac1 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -631,8 +631,8 @@ static int ps8640_probe(struct i2c_client *client) if (!ps_bridge) return -ENOMEM; - ps_bridge->supplies[0].supply = "vdd33"; - ps_bridge->supplies[1].supply = "vdd12"; + ps_bridge->supplies[0].supply = "vdd12"; + ps_bridge->supplies[1].supply = "vdd33"; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies), ps_bridge->supplies); if (ret) From ca5f13a21404f5496bcc006d9416c8bef21b227d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 21 Jul 2022 10:16:55 +0200 Subject: [PATCH 188/396] fbdev: Fix order of arguments to aperture_remove_conflicting_devices() Reverse the order of the final two arguments when calling aperture_remove_conflicting_devices(). An error report is available at [1]. Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Fixes: 8d69d008f44c ("fbdev: Convert drivers to aperture helpers") Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Reviewed-by: Michael Kelley <mikelley@microsoft.com> # hypervfb Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Javier Martinez Canillas <javierm@redhat.com> Cc: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Cc: Teddy Wang <teddy.wang@siliconmotion.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: "K. Y. Srinivasan" <kys@microsoft.com> Cc: Haiyang Zhang <haiyangz@microsoft.com> Cc: Stephen Hemminger <sthemmin@microsoft.com> Cc: Wei Liu <wei.liu@kernel.org> Cc: Dexuan Cui <decui@microsoft.com> Cc: linux-fbdev@vger.kernel.org Cc: linux-hyperv@vger.kernel.org Link: https://lore.kernel.org/lkml/202207202040.jS1WcTzN-lkp@intel.com/ # 1 Link: https://patchwork.freedesktop.org/patch/msgid/20220721081655.16128-1-tzimmermann@suse.de --- drivers/video/fbdev/aty/radeon_base.c | 2 +- drivers/video/fbdev/hyperv_fb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index e5e362b8c9da..0a8199985d52 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -2243,7 +2243,7 @@ static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) resource_size_t base = pci_resource_start(pdev, 0); resource_size_t size = pci_resource_len(pdev, 0); - return aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME, false); + return aperture_remove_conflicting_devices(base, size, false, KBUILD_MODNAME); } static int radeonfb_pci_register(struct pci_dev *pdev, diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index a944a6620527..a0e1d70b90d7 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -1077,7 +1077,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) getmem_done: aperture_remove_conflicting_devices(info->apertures->ranges[0].base, info->apertures->ranges[0].size, - KBUILD_MODNAME, false); + false, KBUILD_MODNAME); if (gen2vm) { /* framebuffer is reallocated, clear screen_info to avoid misuse from kexec */ From b62cc8fa824807c00b77a76e78c7417b6bfdf418 Mon Sep 17 00:00:00 2001 From: pengfuyuan <pengfuyuan@kylinos.cn> Date: Fri, 27 May 2022 11:39:03 +0800 Subject: [PATCH 189/396] drm/arm: Fix spelling typo in comments Fix spelling typo in comments. Reported-by: k2ci <kernel-bot@kylinos.cn> Signed-off-by: pengfuyuan <pengfuyuan@kylinos.cn> Acked-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220426121639.39160-1-pengfuyuan@kylinos.cn --- drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c | 2 +- drivers/gpu/drm/arm/malidp_regs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c index e672b9cffee3..3276a3e82c62 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c @@ -1271,7 +1271,7 @@ int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe, return 0; } -/* Since standalong disabled components must be disabled separately and in the +/* Since standalone disabled components must be disabled separately and in the * last, So a complete disable operation may needs to call pipeline_disable * twice (two phase disabling). * Phase 1: disable the common components, flush it. diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index 514c50dcb74d..3bc16db70ddb 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h @@ -145,7 +145,7 @@ #define MALIDP_SE_COEFFTAB_DATA_MASK 0x3fff #define MALIDP_SE_SET_COEFFTAB_DATA(x) \ ((x) & MALIDP_SE_COEFFTAB_DATA_MASK) -/* Enhance coeffents reigster offset */ +/* Enhance coefficients register offset */ #define MALIDP_SE_IMAGE_ENH 0x3C /* ENH_LIMITS offset 0x0 */ #define MALIDP_SE_ENH_LOW_LEVEL 24 From 4b760f76dd6f57cb0d608ba0c4009b7eeeddd864 Mon Sep 17 00:00:00 2001 From: Robin Murphy <robin.murphy@arm.com> Date: Wed, 15 Jun 2022 17:09:15 +0100 Subject: [PATCH 190/396] drm/arm/hdlcd: Take over EFI framebuffer properly The Arm Juno board EDK2 port has provided an EFI GOP display via HDLCD0 for some time now, which works nicely as an early framebuffer. However, once the HDLCD driver probes and takes over the hardware, it should take over the logical framebuffer as well, otherwise the now-defunct GOP device hangs about and virtual console output inevitably disappears into the wrong place most of the time. We'll do this after binding the HDMI encoder, since that's the most likely thing to fail, and the EFI console is still better than nothing when that happens. However, the two HDLCD controllers on Juno are independent, and many users will still be using older firmware without any display support, so we'll only bother if we find that the HDLCD we're probing is already enabled. And if it is, then we'll also stop it, since otherwise the display can end up shifted if it's still scanning out while the rest of the registers are subsequently reconfigured. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/31acd57f4aa8a4d02877026fa3a8c8d035e15a0d.1655309004.git.robin.murphy@arm.com --- drivers/gpu/drm/arm/hdlcd_drv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index e89ae0ec60eb..60a27886248c 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_debugfs.h> @@ -314,6 +315,15 @@ static int hdlcd_drm_bind(struct device *dev) goto err_vblank; } + /* + * If EFI left us running, take over from simple framebuffer + * drivers. Read HDLCD_REG_COMMAND to see if we are enabled. + */ + if (hdlcd_read(hdlcd, HDLCD_REG_COMMAND)) { + hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0); + drm_aperture_remove_framebuffers(false, &hdlcd_driver); + } + drm_mode_config_reset(drm); drm_kms_helper_poll_init(drm); From f818eac130d236d41c2f18fd475ebd709e5a56e7 Mon Sep 17 00:00:00 2001 From: Robin Murphy <robin.murphy@arm.com> Date: Wed, 15 Jun 2022 17:11:09 +0100 Subject: [PATCH 191/396] drm/arm/hdlcd: Simplify IRQ install/uninstall Since we no longer need to conform to the structure of the various DRM IRQ callbacks, we can streamline the code by consolidating the piecemeal functions and passing around our private data structure directly. We're also a platform device so should never see IRQ_NOTCONNECTED either. Furthermore we can also get rid of all the unnecesary read-modify-write operations, since on install we know we cleared the whole interrupt mask before enabling the debug IRQs, and thus on uninstall we're always clearing everything as well. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/65cf7818b23c1a8629dc851f1d058ecb8a14849e.1655309413.git.robin.murphy@arm.com --- drivers/gpu/drm/arm/hdlcd_drv.c | 62 +++++++++------------------------ 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 60a27886248c..350ca4e4eaa6 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -41,8 +41,7 @@ static irqreturn_t hdlcd_irq(int irq, void *arg) { - struct drm_device *drm = arg; - struct hdlcd_drm_private *hdlcd = drm->dev_private; + struct hdlcd_drm_private *hdlcd = arg; unsigned long irq_status; irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS); @@ -70,61 +69,32 @@ static irqreturn_t hdlcd_irq(int irq, void *arg) return IRQ_HANDLED; } -static void hdlcd_irq_preinstall(struct drm_device *drm) -{ - struct hdlcd_drm_private *hdlcd = drm->dev_private; - /* Ensure interrupts are disabled */ - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0); - hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0); -} - -static void hdlcd_irq_postinstall(struct drm_device *drm) -{ -#ifdef CONFIG_DEBUG_FS - struct hdlcd_drm_private *hdlcd = drm->dev_private; - unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK); - - /* enable debug interrupts */ - irq_mask |= HDLCD_DEBUG_INT_MASK; - - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask); -#endif -} - -static int hdlcd_irq_install(struct drm_device *drm, int irq) +static int hdlcd_irq_install(struct hdlcd_drm_private *hdlcd) { int ret; - if (irq == IRQ_NOTCONNECTED) - return -ENOTCONN; + /* Ensure interrupts are disabled */ + hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0); + hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0); - hdlcd_irq_preinstall(drm); - - ret = request_irq(irq, hdlcd_irq, 0, drm->driver->name, drm); + ret = request_irq(hdlcd->irq, hdlcd_irq, 0, "hdlcd", hdlcd); if (ret) return ret; - hdlcd_irq_postinstall(drm); +#ifdef CONFIG_DEBUG_FS + /* enable debug interrupts */ + hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, HDLCD_DEBUG_INT_MASK); +#endif return 0; } -static void hdlcd_irq_uninstall(struct drm_device *drm) +static void hdlcd_irq_uninstall(struct hdlcd_drm_private *hdlcd) { - struct hdlcd_drm_private *hdlcd = drm->dev_private; /* disable all the interrupts that we might have enabled */ - unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK); + hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0); -#ifdef CONFIG_DEBUG_FS - /* disable debug interrupts */ - irq_mask &= ~HDLCD_DEBUG_INT_MASK; -#endif - - /* disable vsync interrupts */ - irq_mask &= ~HDLCD_INTERRUPT_VSYNC; - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask); - - free_irq(hdlcd->irq, drm); + free_irq(hdlcd->irq, hdlcd); } static int hdlcd_load(struct drm_device *drm, unsigned long flags) @@ -184,7 +154,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags) goto irq_fail; hdlcd->irq = ret; - ret = hdlcd_irq_install(drm, hdlcd->irq); + ret = hdlcd_irq_install(hdlcd); if (ret < 0) { DRM_ERROR("failed to install IRQ handler\n"); goto irq_fail; @@ -345,7 +315,7 @@ err_pm_active: err_unload: of_node_put(hdlcd->crtc.port); hdlcd->crtc.port = NULL; - hdlcd_irq_uninstall(drm); + hdlcd_irq_uninstall(hdlcd); of_reserved_mem_device_release(drm->dev); err_free: drm_mode_config_cleanup(drm); @@ -367,7 +337,7 @@ static void hdlcd_drm_unbind(struct device *dev) hdlcd->crtc.port = NULL; pm_runtime_get_sync(dev); drm_atomic_helper_shutdown(drm); - hdlcd_irq_uninstall(drm); + hdlcd_irq_uninstall(hdlcd); pm_runtime_put(dev); if (pm_runtime_enabled(dev)) pm_runtime_disable(dev); From 000a2f0498f29b0831496bb1fdab3354b00704a2 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler <carsten.haitzler@arm.com> Date: Mon, 18 Jul 2022 17:00:39 +0100 Subject: [PATCH 192/396] drm/komeda: Add legacy FB support so VT's work as expected The komeda driver doesn't come up with a visible text (FB) mode VT by default as it was missing legacy FB support. It's useful to have a working text VT on a system for debug and general usability, so enable it. You can always toggle CONFIG_FRAMEBUFFER_CONSOLE. Signed-off-by: Carsten Haitzler <carsten.haitzler@arm.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220606114714.175499-1-carsten.haitzler@foss.arm.com --- drivers/gpu/drm/arm/display/komeda/komeda_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c index ba16895690f1..9fce4239d4ad 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c @@ -9,6 +9,7 @@ #include <linux/platform_device.h> #include <linux/component.h> #include <linux/pm_runtime.h> +#include <drm/drm_fb_helper.h> #include <drm/drm_module.h> #include <drm/drm_of.h> #include "komeda_dev.h" @@ -72,6 +73,7 @@ static int komeda_bind(struct device *dev) } dev_set_drvdata(dev, mdrv); + drm_fbdev_generic_setup(&mdrv->kms->base, 32); return 0; From a8ff2cd916e62b740718a908fbaa1e9ec8a147f1 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler <carsten.haitzler@arm.com> Date: Mon, 6 Jun 2022 12:47:13 +0100 Subject: [PATCH 193/396] drm/komeda - At init write GCU control block to handle already on DPU If something has already set up the DPU before the komeda driver comes up, it will fail to init because it was just writing to the SRST bit in the GCU control register and ignoring others. This resulted in TBU bringup stalling and init failing. By writing completely we also set the mode back to 0 (inactive) too and thus TBU bringup works. Signed-off-by: Carsten Haitzler <carsten.haitzler@arm.com> Acked-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220606114714.175499-2-carsten.haitzler@foss.arm.com --- drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c index daa1faccd3e7..6c56f5662bc7 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c @@ -310,8 +310,7 @@ static int d71_reset(struct d71_dev *d71) u32 __iomem *gcu = d71->gcu_addr; int ret; - malidp_write32_mask(gcu, BLK_CONTROL, - GCU_CONTROL_SRST, GCU_CONTROL_SRST); + malidp_write32(gcu, BLK_CONTROL, GCU_CONTROL_SRST); ret = dp_wait_cond(!(malidp_read32(gcu, BLK_CONTROL) & GCU_CONTROL_SRST), 100, 1000, 10000); From eaa225b6b52233d45457fd33730e1528c604d92d Mon Sep 17 00:00:00 2001 From: Liviu Dudau <liviu.dudau@arm.com> Date: Fri, 8 Jul 2022 16:39:21 +0100 Subject: [PATCH 194/396] drm/komeda: Fix handling of atomic commits in the atomic_commit_tail hook Komeda driver relies on the generic DRM atomic helper functions to handle commits. It only implements an atomic_commit_tail hook for the mode_config_helper_funcs and even that one is pretty close to the generic implementation with the exception of additional dma_fence signalling. What the generic helper framework doesn't do is waiting for the actual hardware to signal that the commit parameters have been written into the appropriate registers. As we signal CRTC events only on the irq handlers, we need to flush the configuration and wait for the hardware to respond. Add the Komeda specific implementation for atomic_commit_hw_done() that flushes and waits for flip done before calling drm_atomic_helper_commit_hw_done(). The fix was prompted by a patch from Carsten Haitzler where he was trying to solve the same issue but in a different way that I think can lead to wrong event signaling to userspace. Reported-by: Carsten Haitzler <carsten.haitzler@arm.com> Tested-by: Carsten Haitzler <carsten.haitzler@arm.com> Reviewed-by: Carsten Haitzler <carsten.haitzler@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220722122139.288486-1-liviu.dudau@arm.com --- .../gpu/drm/arm/display/komeda/komeda_crtc.c | 4 ++-- .../gpu/drm/arm/display/komeda/komeda_kms.c | 21 ++++++++++++++++++- .../gpu/drm/arm/display/komeda/komeda_kms.h | 2 ++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 59172acb9738..292f533d8cf0 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -235,7 +235,7 @@ void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, crtc->state->event = NULL; drm_crtc_send_vblank_event(crtc, event); } else { - DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n", + DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n", drm_crtc_index(&kcrtc->base)); } spin_unlock_irqrestore(&crtc->dev->event_lock, flags); @@ -286,7 +286,7 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc, komeda_crtc_do_flush(crtc, old); } -static void +void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, struct completion *input_flip_done) { diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 93b7f09b96ca..327051bba5b6 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -69,6 +69,25 @@ static const struct drm_driver komeda_kms_driver = { .minor = 1, }; +static void komeda_kms_atomic_commit_hw_done(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct komeda_kms_dev *kms = to_kdev(dev); + int i; + + for (i = 0; i < kms->n_crtcs; i++) { + struct komeda_crtc *kcrtc = &kms->crtcs[i]; + + if (kcrtc->base.state->active) { + struct completion *flip_done = NULL; + if (kcrtc->base.state->event) + flip_done = kcrtc->base.state->event->base.completion; + komeda_crtc_flush_and_wait_for_flip_done(kcrtc, flip_done); + } + } + drm_atomic_helper_commit_hw_done(state); +} + static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) { struct drm_device *dev = old_state->dev; @@ -81,7 +100,7 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) drm_atomic_helper_commit_modeset_enables(dev, old_state); - drm_atomic_helper_commit_hw_done(old_state); + komeda_kms_atomic_commit_hw_done(old_state); drm_atomic_helper_wait_for_flip_done(dev, old_state); diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h index 7889e380ab23..7339339ef6b8 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h @@ -183,6 +183,8 @@ void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms); void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, struct komeda_events *evts); +void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, + struct completion *input_flip_done); struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev); void komeda_kms_detach(struct komeda_kms_dev *kms); From bbb6f93f51a19787f455768015e9a77a4d83c4c8 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas <javierm@redhat.com> Date: Fri, 22 Jul 2022 09:47:55 +0200 Subject: [PATCH 195/396] drm/bridge: ti-sn65dsi86: Use dev_err_probe() to avoid polluting the log If devm_drm_of_get_bridge() can't find the connected bridge, it returns an ERR_PTR(-EPROBE_DEFER) to indicate that the probe should be deferred. But this path also prints an error message, which pollutes the kernel log since is printed on every probe deferral, i.e: $ dmesg | grep "failed to create panel bridge" | wc -l 38 Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220722074755.660258-1-javierm@redhat.com --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 369bf72717f6..90bbabde1595 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1206,10 +1206,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, int ret; pdata->next_bridge = devm_drm_of_get_bridge(pdata->dev, np, 1, 0); - if (IS_ERR(pdata->next_bridge)) { - DRM_ERROR("failed to create panel bridge\n"); - return PTR_ERR(pdata->next_bridge); - } + if (IS_ERR(pdata->next_bridge)) + return dev_err_probe(pdata->dev, PTR_ERR(pdata->next_bridge), + "failed to create panel bridge\n"); ti_sn_bridge_parse_lanes(pdata, np); From 97216fefed6d9782c7208cca33a5465212f533f3 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 20 Jul 2022 10:30:52 +0200 Subject: [PATCH 196/396] drm/vmwgfx: Remove trailing whitespace Fix coding style. No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Zack Rusin <zackr@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220720083058.15371-2-tzimmermann@suse.de --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ff2f735bbe7a..c720a277489b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2257,7 +2257,7 @@ out_fini: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); mutex_unlock(&dev->mode_config.mutex); - + return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index c89ad3a2d141..b29e650d77f4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -1383,6 +1383,6 @@ out_revert: vmw_validation_revert(&val_ctx); out_unref: vmw_validation_unref_lists(&val_ctx); - + return ret; } From 382fc1f681324bb38bedfe763107a60256c4ddc8 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 20 Jul 2022 10:30:53 +0200 Subject: [PATCH 197/396] drm/atomic-helper: Move DRM_PLANE_HELPER_NO_SCALING to atomic helpers The macro DRM_PLANE_HELPER_NO_SCALING is only useful with the interfaces in drm_atomic_helper.h, but defined in drm_plane_helper.h. So half of DRM includes the latter header file for using this macro. Move the macro and remove the include statements. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720083058.15371-3-tzimmermann@suse.de --- drivers/gpu/drm/arm/hdlcd_crtc.c | 1 - drivers/gpu/drm/ast/ast_mode.c | 1 - drivers/gpu/drm/drm_simple_kms_helper.c | 1 - drivers/gpu/drm/i915/display/i9xx_plane.c | 1 - drivers/gpu/drm/i915/display/intel_cursor.c | 1 - drivers/gpu/drm/i915/display/intel_sprite.c | 1 - drivers/gpu/drm/i915/display/skl_universal_plane.c | 1 - drivers/gpu/drm/imx/ipuv3-plane.c | 1 - drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 1 - drivers/gpu/drm/kmb/kmb_plane.c | 1 - drivers/gpu/drm/logicvc/logicvc_layer.c | 1 - drivers/gpu/drm/mediatek/mtk_drm_plane.c | 1 - drivers/gpu/drm/meson/meson_plane.c | 1 - drivers/gpu/drm/mxsfb/lcdif_kms.c | 1 - drivers/gpu/drm/mxsfb/mxsfb_kms.c | 1 - drivers/gpu/drm/nouveau/dispnv50/base507c.c | 1 - drivers/gpu/drm/nouveau/dispnv50/curs507a.c | 1 - drivers/gpu/drm/nouveau/dispnv50/ovly507e.c | 1 - drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c | 1 - drivers/gpu/drm/rcar-du/rcar_du_plane.c | 1 - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 1 - drivers/gpu/drm/sprd/sprd_dpu.c | 1 - drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 1 - drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 1 - drivers/gpu/drm/tests/drm_plane_helper_test.c | 1 - drivers/gpu/drm/virtio/virtgpu_plane.c | 1 - drivers/gpu/drm/vkms/vkms_plane.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 1 - drivers/gpu/drm/xlnx/zynqmp_disp.c | 1 - include/drm/drm_atomic_helper.h | 9 +++++++++ include/drm/drm_plane_helper.h | 9 --------- 31 files changed, 9 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index afc9cd856501..3313d75a8860 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -23,7 +23,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 214b10178454..7fd2e20f743d 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -42,7 +42,6 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_vram_helper.h> #include <drm/drm_managed.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 36633590ebf3..64800f158e69 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -12,7 +12,6 @@ #include <drm/drm_drv.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_managed.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 592e5adfed8b..6d22e6edef2a 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -7,7 +7,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "intel_atomic.h" #include "intel_atomic_plane.h" diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index c2797ad2d313..e49927965a6b 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -8,7 +8,6 @@ #include <drm/drm_atomic_uapi.h> #include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_fourcc.h> #include "intel_atomic.h" diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 2713faad0625..a10c29226289 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -39,7 +39,6 @@ #include <drm/drm_crtc.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_rect.h> #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index c11e15a93164..87c202ec7d1e 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -7,7 +7,6 @@ #include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "i915_drv.h" #include "intel_atomic_plane.h" diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index ea5f594955df..26a0e2e2a366 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -14,7 +14,6 @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> -#include <drm/drm_plane_helper.h> #include <video/imx-ipu-v3.h> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 4de729bbf152..be699cc993d5 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -41,7 +41,6 @@ #include <drm/drm_of.h> #include <drm/drm_panel.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c index 89d055a089a6..563b04ca80ee 100644 --- a/drivers/gpu/drm/kmb/kmb_plane.c +++ b/drivers/gpu/drm/kmb/kmb_plane.c @@ -14,7 +14,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> -#include <drm/drm_plane_helper.h> #include "kmb_drv.h" #include "kmb_plane.h" diff --git a/drivers/gpu/drm/logicvc/logicvc_layer.c b/drivers/gpu/drm/logicvc/logicvc_layer.c index 441e3cfce4cf..adeea9fd11d5 100644 --- a/drivers/gpu/drm/logicvc/logicvc_layer.c +++ b/drivers/gpu/drm/logicvc/logicvc_layer.c @@ -14,7 +14,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include "logicvc_crtc.h" diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index 5c0d9ce69931..414269b0f8bc 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -11,7 +11,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index b9ac932af8d0..973ea08ad1a7 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -20,7 +20,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include "meson_plane.h" #include "meson_registers.h" diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index 1bec1279c8b5..6b52280e3702 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -23,7 +23,6 @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "lcdif_drv.h" diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index e38ce5737a5f..1279b4e1697d 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -26,7 +26,6 @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "mxsfb_drv.h" diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c index 788db043a342..65cefaaf88f6 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c @@ -30,7 +30,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "nouveau_bo.h" diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c index 00e19fd959ea..24f7b1963a2a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c +++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c @@ -29,7 +29,6 @@ #include <nvhw/class/cl507a.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> bool curs507a_space(struct nv50_wndw *wndw) diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c index afd6c7271de1..41ac9c67667c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c @@ -24,7 +24,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <nvif/cl507e.h> #include <nvif/event.h> diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index 183d2c0e65b6..b8e4c44c0854 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -23,7 +23,6 @@ #include "atom.h" #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <nouveau_bo.h> #include <nvif/clc37e.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index e98b76db703a..473f634da964 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -16,7 +16,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include "rcar_du_drv.h" #include "rcar_du_group.h" diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index ad3958b6f8bf..efc783c8f653 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -27,7 +27,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_self_refresh_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c index 3664089b6983..03e760260d9c 100644 --- a/drivers/gpu/drm/sprd/sprd_dpu.c +++ b/drivers/gpu/drm/sprd/sprd_dpu.c @@ -23,7 +23,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> #include "sprd_drm.h" #include "sprd_dpu.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 36da962de394..da1d4ec2e22b 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -18,7 +18,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include "sun8i_mixer.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 1fee6499bdd3..4bd295c2d340 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -11,7 +11,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include "sun8i_csc.h" diff --git a/drivers/gpu/drm/tests/drm_plane_helper_test.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c index e298766cd41f..ec1654cdfc42 100644 --- a/drivers/gpu/drm/tests/drm_plane_helper_test.c +++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c @@ -9,7 +9,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_modes.h> static void set_src(struct drm_plane_state *plane_state, diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 6a62f327dc09..0e1aa4e206e8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -26,7 +26,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "virtgpu_drv.h" diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index d8eb674b49a6..22238db6f8a5 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -7,7 +7,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> #include "vkms_drv.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index c720a277489b..a19580109f33 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -29,7 +29,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_rect.h> #include <drm/drm_sysfs.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index cc32aa89cf8f..d3bdecabf4e5 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -20,7 +20,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_managed.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include <linux/clk.h> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 2a0b17842402..ab778aad7359 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -34,6 +34,15 @@ #include <drm/drm_atomic_state_helper.h> #include <drm/drm_util.h> +/* + * Drivers that don't allow primary plane scaling may pass this macro in place + * of the min/max scale parameters of the plane-state checker function. + * + * Due to src being in 16.16 fixed point and dest being in integer pixels, + * 1<<16 represents no scaling. + */ +#define DRM_PLANE_HELPER_NO_SCALING (1<<16) + struct drm_atomic_state; struct drm_private_obj; struct drm_private_state; diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 331ebd60b3a3..ff85ef41cb33 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -29,15 +29,6 @@ #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_modeset_helper.h> -/* - * Drivers that don't allow primary plane scaling may pass this macro in place - * of the min/max scale parameters of the update checker function. - * - * Due to src being in 16.16 fixed point and dest being in integer pixels, - * 1<<16 represents no scaling. - */ -#define DRM_PLANE_HELPER_NO_SCALING (1<<16) - void drm_primary_helper_destroy(struct drm_plane *plane); extern const struct drm_plane_funcs drm_primary_helper_funcs; From cce32e4e38c63f040ffe1966117d364ecf9a28b8 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 20 Jul 2022 10:30:54 +0200 Subject: [PATCH 198/396] drm/atomic-helper: Remove _HELPER_ infix from DRM_PLANE_HELPER_NO_SCALING Rename DRM_PLANE_HELPER_NO_SCALING to DRM_PLANE_NO_SCALING. The constant is not really a helper, but rather a characteristic of the plane itself. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720083058.15371-4-tzimmermann@suse.de --- drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 4 +-- drivers/gpu/drm/arm/hdlcd_crtc.c | 4 +-- drivers/gpu/drm/ast/ast_mode.c | 8 ++--- drivers/gpu/drm/drm_plane_helper.c | 4 +-- drivers/gpu/drm/drm_simple_kms_helper.c | 4 +-- drivers/gpu/drm/i915/display/i9xx_plane.c | 4 +-- drivers/gpu/drm/i915/display/intel_cursor.c | 4 +-- drivers/gpu/drm/i915/display/intel_sprite.c | 8 ++--- .../drm/i915/display/skl_universal_plane.c | 4 +-- drivers/gpu/drm/imx/ipuv3-plane.c | 4 +-- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 4 +-- drivers/gpu/drm/kmb/kmb_plane.c | 4 +-- drivers/gpu/drm/logicvc/logicvc_layer.c | 4 +-- drivers/gpu/drm/mediatek/mtk_drm_plane.c | 8 ++--- drivers/gpu/drm/meson/meson_plane.c | 2 +- drivers/gpu/drm/mxsfb/lcdif_kms.c | 4 +-- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 4 +-- drivers/gpu/drm/nouveau/dispnv50/base507c.c | 4 +-- drivers/gpu/drm/nouveau/dispnv50/curs507a.c | 4 +-- drivers/gpu/drm/nouveau/dispnv50/ovly507e.c | 4 +-- drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c | 4 +-- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 ++--- drivers/gpu/drm/sprd/sprd_dpu.c | 4 +-- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 4 +-- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +-- drivers/gpu/drm/tests/drm_plane_helper_test.c | 32 +++++++++---------- drivers/gpu/drm/vboxvideo/vbox_mode.c | 8 ++--- drivers/gpu/drm/virtio/virtgpu_plane.c | 4 +-- drivers/gpu/drm/vkms/vkms_plane.c | 4 +-- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 ++--- drivers/gpu/drm/xlnx/zynqmp_disp.c | 4 +-- include/drm/drm_atomic_helper.h | 2 +- 33 files changed, 90 insertions(+), 90 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index 576849e95296..f4b5301ea2a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -282,8 +282,8 @@ static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane, return PTR_ERR(crtc_state); ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); if (ret != 0) return ret; diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 3313d75a8860..636ef9447830 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -251,8 +251,8 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane, return -EINVAL; return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 7fd2e20f743d..103bd4fa698b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -554,8 +554,8 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, new_plane_state->crtc); ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); if (ret) return ret; @@ -778,8 +778,8 @@ static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, new_plane_state->crtc); ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 838b32b70bce..bc08edd69030 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -179,8 +179,8 @@ static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *c ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, DRM_MODE_ROTATE_0, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false, &visible); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 64800f158e69..e9f782119d3d 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -222,8 +222,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, &pipe->crtc); ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 6d22e6edef2a..0f35f2facdfc 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -325,8 +325,8 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, return ret; ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, i9xx_plane_has_windowing(plane)); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index e49927965a6b..16ac560eab49 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -143,8 +143,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, } ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index a10c29226289..7649c50b5445 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -1354,8 +1354,8 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - int min_scale = DRM_PLANE_HELPER_NO_SCALING; - int max_scale = DRM_PLANE_HELPER_NO_SCALING; + int min_scale = DRM_PLANE_NO_SCALING; + int max_scale = DRM_PLANE_NO_SCALING; int ret; if (g4x_fb_scalable(plane_state->hw.fb)) { @@ -1425,8 +1425,8 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, return ret; ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 87c202ec7d1e..4d6a27757065 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1855,8 +1855,8 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; - int min_scale = DRM_PLANE_HELPER_NO_SCALING; - int max_scale = DRM_PLANE_HELPER_NO_SCALING; + int min_scale = DRM_PLANE_NO_SCALING; + int max_scale = DRM_PLANE_NO_SCALING; int ret; ret = skl_plane_check_fb(crtc_state, plane_state); diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 26a0e2e2a366..f1b397693af8 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -392,8 +392,8 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, return -EINVAL; ret = drm_atomic_helper_check_plane_state(new_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, can_position, true); if (ret) return ret; diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index be699cc993d5..f5835e6bf877 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -481,8 +481,8 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, return PTR_ERR(priv_state); ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, priv->soc_info->has_osd, true); if (ret) diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c index 563b04ca80ee..e385b8741776 100644 --- a/drivers/gpu/drm/kmb/kmb_plane.c +++ b/drivers/gpu/drm/kmb/kmb_plane.c @@ -135,8 +135,8 @@ static int kmb_plane_atomic_check(struct drm_plane *plane, new_plane_state->crtc); return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, can_position, true); } diff --git a/drivers/gpu/drm/logicvc/logicvc_layer.c b/drivers/gpu/drm/logicvc/logicvc_layer.c index adeea9fd11d5..466f9bd88bc1 100644 --- a/drivers/gpu/drm/logicvc/logicvc_layer.c +++ b/drivers/gpu/drm/logicvc/logicvc_layer.c @@ -116,8 +116,8 @@ static int logicvc_plane_atomic_check(struct drm_plane *drm_plane, } } - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; + min_scale = DRM_PLANE_NO_SCALING; + max_scale = DRM_PLANE_NO_SCALING; can_position = (drm_plane->type == DRM_PLANE_TYPE_OVERLAY && layer->index != (logicvc->config.layers_count - 1) && diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index 414269b0f8bc..2f5e007dd380 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -107,8 +107,8 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane, crtc_state = new_plane_state->crtc->state; return drm_atomic_helper_check_plane_state(plane->state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); } @@ -201,8 +201,8 @@ static int mtk_plane_atomic_check(struct drm_plane *plane, return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); } diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 973ea08ad1a7..f3d49e81acf4 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -94,7 +94,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane, return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, FRAC_16_16(1, 5), - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); } diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index 6b52280e3702..b27a54e31343 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -392,8 +392,8 @@ static int lcdif_plane_atomic_check(struct drm_plane *plane, &lcdif->crtc); return drm_atomic_helper_check_plane_state(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); } diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 1279b4e1697d..2da2be6c11f2 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -530,8 +530,8 @@ static int mxsfb_plane_atomic_check(struct drm_plane *plane, &mxsfb->crtc); return drm_atomic_helper_check_plane_state(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c index 65cefaaf88f6..63f6ee6797bc 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c @@ -237,8 +237,8 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int ret; ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c index 24f7b1963a2a..ec646a6f48d1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c +++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c @@ -102,8 +102,8 @@ curs507a_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int ret; ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); asyh->curs.visible = asyw->state.visible; if (ret || !asyh->curs.visible) diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c index 41ac9c67667c..8c2da56defe0 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c @@ -106,8 +106,8 @@ ovly507e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int ret; ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index b8e4c44c0854..9cf599d14ce8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -296,8 +296,8 @@ wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, struct nv50_head_atom *asyh) { return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 473f634da964..8e729cc4c209 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -594,8 +594,8 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane, return PTR_ERR(crtc_state); ret = drm_atomic_helper_check_plane_state(state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index efc783c8f653..bdd48f87d098 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -808,9 +808,9 @@ static int vop_plane_atomic_check(struct drm_plane *plane, const struct vop_win_data *win = vop_win->data; int ret; int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : - DRM_PLANE_HELPER_NO_SCALING; + DRM_PLANE_NO_SCALING; int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : - DRM_PLANE_HELPER_NO_SCALING; + DRM_PLANE_NO_SCALING; if (!crtc || WARN_ON(!fb)) return 0; @@ -1059,9 +1059,9 @@ static int vop_plane_atomic_async_check(struct drm_plane *plane, struct vop_win *vop_win = to_vop_win(plane); const struct vop_win_data *win = vop_win->data; int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : - DRM_PLANE_HELPER_NO_SCALING; + DRM_PLANE_NO_SCALING; int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : - DRM_PLANE_HELPER_NO_SCALING; + DRM_PLANE_NO_SCALING; struct drm_crtc_state *crtc_state; if (plane != new_plane_state->crtc->cursor) diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c index 03e760260d9c..10d21f7ab02d 100644 --- a/drivers/gpu/drm/sprd/sprd_dpu.c +++ b/drivers/gpu/drm/sprd/sprd_dpu.c @@ -523,8 +523,8 @@ static int sprd_plane_atomic_check(struct drm_plane *plane, return PTR_ERR(crtc_state); return drm_atomic_helper_check_plane_state(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); } diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index da1d4ec2e22b..06ed571c37f0 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -245,8 +245,8 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane, if (WARN_ON(!crtc_state)) return -EINVAL; - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; + min_scale = DRM_PLANE_NO_SCALING; + max_scale = DRM_PLANE_NO_SCALING; if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) { min_scale = SUN8I_UI_SCALER_SCALE_MIN; diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 4bd295c2d340..b9473efa308d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -379,8 +379,8 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, if (WARN_ON(!crtc_state)) return -EINVAL; - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; + min_scale = DRM_PLANE_NO_SCALING; + max_scale = DRM_PLANE_NO_SCALING; if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) { min_scale = SUN8I_VI_SCALER_SCALE_MIN; diff --git a/drivers/gpu/drm/tests/drm_plane_helper_test.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c index ec1654cdfc42..be6cff0020ed 100644 --- a/drivers/gpu/drm/tests/drm_plane_helper_test.c +++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c @@ -104,8 +104,8 @@ static void igt_check_plane_state(struct kunit *test) set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16); set_crtc(&plane_state, 0, 0, fb.width, fb.height); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple clipping check should pass\n"); KUNIT_EXPECT_TRUE(test, plane_state.visible); @@ -115,8 +115,8 @@ static void igt_check_plane_state(struct kunit *test) /* Rotated clipping + reflection, no scaling. */ plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X; ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Rotated clipping check should pass\n"); KUNIT_EXPECT_TRUE(test, plane_state.visible); @@ -128,15 +128,15 @@ static void igt_check_plane_state(struct kunit *test) set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16); set_crtc(&plane_state, 0, 0, 1023, 767); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); KUNIT_EXPECT_TRUE_MSG(test, ret, "Should not be able to position on the crtc with can_position=false\n"); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple positioning should work\n"); KUNIT_EXPECT_TRUE(test, plane_state.visible); @@ -148,12 +148,12 @@ static void igt_check_plane_state(struct kunit *test) set_crtc(&plane_state, 0, 0, 1024, 768); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, 0x8001, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); KUNIT_EXPECT_TRUE_MSG(test, ret, "Upscaling out of range should fail.\n"); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, 0x8000, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Upscaling exactly 2x should work\n"); KUNIT_EXPECT_TRUE(test, plane_state.visible); @@ -162,11 +162,11 @@ static void igt_check_plane_state(struct kunit *test) set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, 0x1ffff, false, false); KUNIT_EXPECT_TRUE_MSG(test, ret, "Downscaling out of range should fail.\n"); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, 0x20000, false, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed with exact scaling limit\n"); KUNIT_EXPECT_TRUE(test, plane_state.visible); @@ -177,7 +177,7 @@ static void igt_check_plane_state(struct kunit *test) set_src(&plane_state, 0, 0, 0x40001, 0x40001); set_crtc(&plane_state, 1022, 766, 4, 4); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, 0x10001, true, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); @@ -188,7 +188,7 @@ static void igt_check_plane_state(struct kunit *test) set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001); set_crtc(&plane_state, -2, -2, 1028, 772); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, 0x10001, false, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); @@ -201,7 +201,7 @@ static void igt_check_plane_state(struct kunit *test) set_crtc(&plane_state, 1022, 766, 4, 4); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, 0xffff, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, true, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); KUNIT_EXPECT_TRUE(test, plane_state.visible); @@ -213,7 +213,7 @@ static void igt_check_plane_state(struct kunit *test) set_crtc(&plane_state, -2, -2, 1028, 772); ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, 0xffff, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple"); KUNIT_EXPECT_TRUE(test, plane_state.visible); diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c index fa0d73ce07bc..604ebfbef314 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c @@ -269,8 +269,8 @@ static int vbox_primary_atomic_check(struct drm_plane *plane, } return drm_atomic_helper_check_plane_state(new_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); } @@ -351,8 +351,8 @@ static int vbox_cursor_atomic_check(struct drm_plane *plane, } ret = drm_atomic_helper_check_plane_state(new_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); if (ret) return ret; diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 0e1aa4e206e8..c599c99f228e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -93,8 +93,8 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, return PTR_ERR(crtc_state); ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, is_cursor, true); return ret; } diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 22238db6f8a5..8a810bfa1264 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -138,8 +138,8 @@ static int vkms_plane_atomic_check(struct drm_plane *plane, can_position = true; ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, can_position, true); if (ret != 0) return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index a19580109f33..214829c32ed8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -719,8 +719,8 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, new_state->crtc); ret = drm_atomic_helper_check_plane_state(new_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, true); if (!ret && new_fb) { @@ -761,8 +761,8 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, new_state->crtc); ret = drm_atomic_helper_check_plane_state(new_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); if (ret) return ret; diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index d3bdecabf4e5..a769422e3f1d 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -1150,8 +1150,8 @@ zynqmp_disp_plane_atomic_check(struct drm_plane *plane, return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, false, false); } diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index ab778aad7359..54b321f20d53 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -41,7 +41,7 @@ * Due to src being in 16.16 fixed point and dest being in integer pixels, * 1<<16 represents no scaling. */ -#define DRM_PLANE_HELPER_NO_SCALING (1<<16) +#define DRM_PLANE_NO_SCALING (1<<16) struct drm_atomic_state; struct drm_private_obj; From 254e5e8829a97bdbaf86b83ef704ac45a30c3867 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 20 Jul 2022 10:30:55 +0200 Subject: [PATCH 199/396] drm: Remove unnecessary include statements of drm_plane_helper.h Remove the include statement for drm_plane_helper.h from all the files that don't need it. Althogh the header file is almost empty, many drivers include it somewhere. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720083058.15371-5-tzimmermann@suse.de --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 - drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | 1 - drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 1 - drivers/gpu/drm/arm/malidp_planes.c | 1 - drivers/gpu/drm/armada/armada_crtc.c | 1 - drivers/gpu/drm/armada/armada_overlay.c | 1 - drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 1 - drivers/gpu/drm/drm_crtc_helper.c | 1 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 1 - drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 1 - drivers/gpu/drm/gma500/psb_intel_display.c | 2 -- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 1 - drivers/gpu/drm/i915/display/intel_atomic.c | 1 - drivers/gpu/drm/i915/display/intel_atomic_plane.c | 1 - drivers/gpu/drm/i915/display/intel_crtc.c | 1 - drivers/gpu/drm/i915/display/intel_display.c | 1 - drivers/gpu/drm/i915/intel_pm.c | 1 - drivers/gpu/drm/imx/imx-drm-core.c | 1 - drivers/gpu/drm/ingenic/ingenic-ipu.c | 1 - drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 1 - drivers/gpu/drm/meson/meson_overlay.c | 1 - drivers/gpu/drm/mgag200/mgag200_mode.c | 1 - drivers/gpu/drm/msm/msm_drv.h | 1 - drivers/gpu/drm/nouveau/dispnv50/disp.c | 1 - drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c | 1 - drivers/gpu/drm/omapdrm/omap_crtc.c | 1 - drivers/gpu/drm/omapdrm/omap_overlay.c | 1 - drivers/gpu/drm/omapdrm/omap_plane.c | 1 - drivers/gpu/drm/radeon/radeon_display.c | 1 - drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 1 - drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 1 - drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 1 - drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 1 - drivers/gpu/drm/sti/sti_crtc.c | 1 - drivers/gpu/drm/sti/sti_plane.h | 1 - drivers/gpu/drm/stm/ltdc.c | 1 - drivers/gpu/drm/sun4i/sun4i_backend.c | 1 - drivers/gpu/drm/sun4i/sun4i_layer.c | 1 - drivers/gpu/drm/sun4i/sun8i_mixer.c | 1 - drivers/gpu/drm/tegra/dc.c | 1 - drivers/gpu/drm/tegra/plane.c | 1 - drivers/gpu/drm/tidss/tidss_crtc.c | 1 - drivers/gpu/drm/tilcdc/tilcdc_plane.c | 1 - drivers/gpu/drm/vc4/vc4_kms.c | 1 - drivers/gpu/drm/vc4/vc4_plane.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 - 49 files changed, 50 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index d788a00043a5..37322550d750 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -38,7 +38,6 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 292f533d8cf0..4cc07d6bb9d8 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -11,7 +11,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index dff22dec54b5..c20ff72f0ae5 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -7,7 +7,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include "komeda_dev.h" #include "komeda_kms.h" diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 8a9562642d16..a1cee1a5b523 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -18,7 +18,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include "malidp_hw.h" diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index b7bb90ae787f..15dd667aa2e7 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -12,7 +12,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 424250535fed..1db77549189e 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -9,7 +9,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "armada_crtc.h" #include "armada_drm.h" diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 2306ceb3e999..10f31faf140c 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -16,7 +16,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include "atmel_hlcdc_dc.h" diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8bf41aa24068..c6abfd3d4b62 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -38,7 +38,6 @@ #include <drm/drm_drv.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_self_refresh_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 8a6d54515f92..457448cc60f7 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -45,7 +45,6 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 66e5f1e34044..7c3aa77186d3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -9,7 +9,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_plane_helper.h> #include <drm/exynos_drm.h> #include "exynos_drm_crtc.h" diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index 0cd527f0c146..e4f518e44945 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -14,7 +14,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include "fsl_dcu_drm_drv.h" diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 9a5ea06a1a8e..531c1781a8fb 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -9,8 +9,6 @@ #include <linux/delay.h> #include <linux/i2c.h> -#include <drm/drm_plane_helper.h> - #include "framebuffer.h" #include "gem.h" #include "gma_display.h" diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 61c29c2834e6..2c7059b775a1 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -28,7 +28,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 40da7910f845..b94973b5633f 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,7 +32,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "i915_drv.h" #include "i915_reg.h" diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index efe8591619e3..dd876dbbaa39 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -33,7 +33,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "gt/intel_rps.h" diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 4442aa355f86..6792a9056f46 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -9,7 +9,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank_work.h> #include "i915_irq.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a0f84cbe974f..bf170bd83ef7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -42,7 +42,6 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_edid.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_privacy_screen_consumer.h> #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f06babdb3a8c..ef7553b494ea 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -32,7 +32,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "display/intel_atomic.h" #include "display/intel_atomic_plane.h" diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index a57812ec36b1..50fd7aac5198 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -22,7 +22,6 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_of.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index d13f58ad4769..c117073fd61e 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -29,7 +29,6 @@ #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_property.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 42cc7052b050..112615817dcb 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -15,7 +15,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index b4a0518c1028..93c1cd2aab43 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -16,7 +16,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include "meson_overlay.h" #include "meson_registers.h" diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 225cca2ed60e..a02f599cb9cf 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -20,7 +20,6 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index b3689a2d27d7..7d5fb0fc22dd 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -27,7 +27,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_fb_helper.h> #include <drm/display/drm_dsc.h> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index ade2988e85f3..b73fdfbe58ee 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -39,7 +39,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c index 37f6da8b3f2a..1a9a07c77da1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c @@ -23,7 +23,6 @@ #include "atom.h" #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <nouveau_bo.h> #include <nvif/clc37e.h> diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 06a719c104f4..63ddc5127f7b 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -10,7 +10,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_mode.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "omap_drv.h" diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.c b/drivers/gpu/drm/omapdrm/omap_overlay.c index b0bc9ad2ef73..fb97c74386f2 100644 --- a/drivers/gpu/drm/omapdrm/omap_overlay.c +++ b/drivers/gpu/drm/omapdrm/omap_overlay.c @@ -6,7 +6,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include "omap_dmm_tiler.h" #include "omap_drv.h" diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index b6cb537f7689..24a2ded08b45 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -8,7 +8,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index f12675e3d261..ca5598ae8bfc 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -38,7 +38,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> #include <drm/radeon_drm.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index f361a604337f..227a9be30715 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -19,7 +19,6 @@ #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "rcar_cmm.h" diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index e778fd52f890..44ac95da9c13 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -17,7 +17,6 @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include <linux/bitops.h> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index e4631f515ba4..552426d5d3a2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -29,7 +29,6 @@ #include <drm/drm_debugfs.h> #include <drm/drm_flip_work.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 071a929e9fe3..387fbd2ab32d 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -16,7 +16,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index 409795786f03..3c7154f2d5f3 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c @@ -11,7 +11,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_device.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h index 8e33e629d9b0..2c0156bede9c 100644 --- a/drivers/gpu/drm/sti/sti_plane.h +++ b/drivers/gpu/drm/sti/sti_plane.h @@ -8,7 +8,6 @@ #define _STI_PLANE_H_ #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #define to_sti_plane(x) container_of(x, struct sti_plane, drm_plane) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index da7a0a183b27..8f3307b279e7 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -34,7 +34,6 @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 287e8c4bbaea..0c69eab1fd37 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -23,7 +23,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include "sun4i_backend.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 648dd0b5b116..98f3176366c0 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -10,7 +10,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include "sun4i_backend.h" #include "sun4i_frontend.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 648b38a73066..4e9bd9cb6b36 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -19,7 +19,6 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include "sun4i_drv.h" diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 747abafb6a5c..bd0f60704467 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -26,7 +26,6 @@ #include <drm/drm_debugfs.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "dc.h" diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index ca9f03e3675b..10090116895f 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -12,7 +12,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include "dc.h" #include "plane.h" diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c index 2218da3b3ca3..ad4ce9d06622 100644 --- a/drivers/gpu/drm/tidss/tidss_crtc.c +++ b/drivers/gpu/drm/tidss/tidss_crtc.c @@ -10,7 +10,6 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "tidss_crtc.h" diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 960136518814..0ccf791301cb 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -5,7 +5,6 @@ */ #include <drm/drm_atomic.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index b45dcdfd7306..4419e810103d 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -18,7 +18,6 @@ #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 82a650268f19..243b29ab6f85 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -23,7 +23,6 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include "uapi/drm/vc4_drm.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index e4347faccee0..b8761f16dd78 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -28,7 +28,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "vmwgfx_kms.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index b29e650d77f4..ecd3c2fc978b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -29,7 +29,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "vmwgfx_kms.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index eb014b97d156..8650c3aea8f0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -29,7 +29,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "vmwgfx_kms.h" From 30c637151cfac8da3588f3773462e705a4ff2f59 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 20 Jul 2022 10:30:56 +0200 Subject: [PATCH 200/396] drm/plane-helper: Export individual helpers Export the individual plane helpers that make up the plane functions and align the naming with other helpers. The plane helpers are for non-atomic modesetting and exporting them will simplify a later conversion of drivers to atomic modesetting. With struct drm_plane_funcs removed from drm_plane_helper.h, also remove the include statements. It only needs linux/types.h for uint32_t and a number of forward declarations. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720083058.15371-6-tzimmermann@suse.de --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +- drivers/gpu/drm/armada/armada_plane.c | 2 +- drivers/gpu/drm/drm_modeset_helper.c | 8 ++- drivers/gpu/drm/drm_plane_helper.c | 70 ++++++++++++++----- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 8 ++- drivers/gpu/drm/qxl/qxl_display.c | 4 +- drivers/gpu/drm/vboxvideo/vbox_mode.c | 4 +- include/drm/drm_plane_helper.h | 22 ++++-- 8 files changed, 88 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 41e4774abdb0..e2d7fd78c57b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -85,6 +85,7 @@ #include <drm/drm_vblank.h> #include <drm/drm_audio_component.h> #include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_plane_helper.h> #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" @@ -7717,7 +7718,7 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane, static const struct drm_plane_funcs dm_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_primary_helper_destroy, + .destroy = drm_plane_helper_destroy, .reset = dm_drm_plane_reset, .atomic_duplicate_state = dm_drm_plane_duplicate_state, .atomic_destroy_state = dm_drm_plane_destroy_state, diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c index 959d7f0a5108..cc47c032dbc1 100644 --- a/drivers/gpu/drm/armada/armada_plane.c +++ b/drivers/gpu/drm/armada/armada_plane.c @@ -288,7 +288,7 @@ struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane) static const struct drm_plane_funcs armada_primary_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_primary_helper_destroy, + .destroy = drm_plane_helper_destroy, .reset = armada_plane_reset, .atomic_duplicate_state = armada_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 0f08319453b2..bd609a978848 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -108,6 +108,12 @@ static const uint32_t safe_modeset_formats[] = { DRM_FORMAT_ARGB8888, }; +static const struct drm_plane_funcs primary_plane_funcs = { + .update_plane = drm_plane_helper_update_primary, + .disable_plane = drm_plane_helper_disable_primary, + .destroy = drm_plane_helper_destroy, +}; + static struct drm_plane *create_primary_plane(struct drm_device *dev) { struct drm_plane *primary; @@ -127,7 +133,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev) /* possible_crtc's will be filled in later by crtc_init */ ret = drm_universal_plane_init(dev, primary, 0, - &drm_primary_helper_funcs, + &primary_plane_funcs, safe_modeset_formats, ARRAY_SIZE(safe_modeset_formats), NULL, diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index bc08edd69030..c7785967f5bf 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -145,13 +145,36 @@ static int drm_plane_helper_check_update(struct drm_plane *plane, return 0; } -static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h, - struct drm_modeset_acquire_ctx *ctx) +/** + * drm_plane_helper_update_primary - Helper for updating primary planes + * @plane: plane to update + * @crtc: the plane's new CRTC + * @fb: the plane's new framebuffer + * @crtc_x: x coordinate within CRTC + * @crtc_y: y coordinate within CRTC + * @crtc_w: width coordinate within CRTC + * @crtc_h: height coordinate within CRTC + * @src_x: x coordinate within source + * @src_y: y coordinate within source + * @src_w: width coordinate within source + * @src_h: height coordinate within source + * @ctx: modeset locking context + * + * This helper validates the given parameters and updates the primary plane. + * + * This function is only useful for non-atomic modesetting. Don't use + * it in new drivers. + * + * Returns: + * Zero on success, or an errno code otherwise. + */ +int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h, + struct drm_modeset_acquire_ctx *ctx) { struct drm_mode_set set = { .crtc = crtc, @@ -218,31 +241,40 @@ static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *c kfree(connector_list); return ret; } +EXPORT_SYMBOL(drm_plane_helper_update_primary); -static int drm_primary_helper_disable(struct drm_plane *plane, - struct drm_modeset_acquire_ctx *ctx) +/** + * drm_plane_helper_disable_primary - Helper for disabling primary planes + * @plane: plane to disable + * @ctx: modeset locking context + * + * This helper returns an error when trying to disable the primary + * plane. + * + * This function is only useful for non-atomic modesetting. Don't use + * it in new drivers. + * + * Returns: + * An errno code. + */ +int drm_plane_helper_disable_primary(struct drm_plane *plane, + struct drm_modeset_acquire_ctx *ctx) { return -EINVAL; } +EXPORT_SYMBOL(drm_plane_helper_disable_primary); /** - * drm_primary_helper_destroy() - Helper for primary plane destruction + * drm_plane_helper_destroy() - Helper for primary plane destruction * @plane: plane to destroy * * Provides a default plane destroy handler for primary planes. This handler * is called during CRTC destruction. We disable the primary plane, remove * it from the DRM plane list, and deallocate the plane structure. */ -void drm_primary_helper_destroy(struct drm_plane *plane) +void drm_plane_helper_destroy(struct drm_plane *plane) { drm_plane_cleanup(plane); kfree(plane); } -EXPORT_SYMBOL(drm_primary_helper_destroy); - -const struct drm_plane_funcs drm_primary_helper_funcs = { - .update_plane = drm_primary_helper_update, - .disable_plane = drm_primary_helper_disable, - .destroy = drm_primary_helper_destroy, -}; -EXPORT_SYMBOL(drm_primary_helper_funcs); +EXPORT_SYMBOL(drm_plane_helper_destroy); diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index f9e962fd94d0..660c4cbc0b3d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1275,6 +1275,12 @@ static const uint32_t modeset_formats[] = { DRM_FORMAT_XRGB1555, }; +static const struct drm_plane_funcs nv04_primary_plane_funcs = { + .update_plane = drm_plane_helper_update_primary, + .disable_plane = drm_plane_helper_disable_primary, + .destroy = drm_plane_helper_destroy, +}; + static struct drm_plane * create_primary_plane(struct drm_device *dev) { @@ -1289,7 +1295,7 @@ create_primary_plane(struct drm_device *dev) /* possible_crtc's will be filled in later by crtc_init */ ret = drm_universal_plane_init(dev, primary, 0, - &drm_primary_helper_funcs, + &nv04_primary_plane_funcs, modeset_formats, ARRAY_SIZE(modeset_formats), NULL, DRM_PLANE_TYPE_PRIMARY, NULL); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 2e8949863d6b..a152a7c6db21 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -902,7 +902,7 @@ static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = { static const struct drm_plane_funcs qxl_cursor_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_primary_helper_destroy, + .destroy = drm_plane_helper_destroy, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, @@ -924,7 +924,7 @@ static const struct drm_plane_helper_funcs primary_helper_funcs = { static const struct drm_plane_funcs qxl_primary_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_primary_helper_destroy, + .destroy = drm_plane_helper_destroy, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c index 604ebfbef314..341edd982cb3 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c @@ -477,7 +477,7 @@ static const struct drm_plane_helper_funcs vbox_cursor_helper_funcs = { static const struct drm_plane_funcs vbox_cursor_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_primary_helper_destroy, + .destroy = drm_plane_helper_destroy, DRM_GEM_SHADOW_PLANE_FUNCS, }; @@ -496,7 +496,7 @@ static const struct drm_plane_helper_funcs vbox_primary_helper_funcs = { static const struct drm_plane_funcs vbox_primary_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_primary_helper_destroy, + .destroy = drm_plane_helper_destroy, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index ff85ef41cb33..1781fab24dd6 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -24,12 +24,22 @@ #ifndef DRM_PLANE_HELPER_H #define DRM_PLANE_HELPER_H -#include <drm/drm_rect.h> -#include <drm/drm_crtc.h> -#include <drm/drm_modeset_helper_vtables.h> -#include <drm/drm_modeset_helper.h> +#include <linux/types.h> -void drm_primary_helper_destroy(struct drm_plane *plane); -extern const struct drm_plane_funcs drm_primary_helper_funcs; +struct drm_crtc; +struct drm_framebuffer; +struct drm_modeset_acquire_ctx; +struct drm_plane; + +int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h, + struct drm_modeset_acquire_ctx *ctx); +int drm_plane_helper_disable_primary(struct drm_plane *plane, + struct drm_modeset_acquire_ctx *ctx); +void drm_plane_helper_destroy(struct drm_plane *plane); #endif From 62d89fee3defe841ce12b46439f9b34010bd616a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 20 Jul 2022 10:30:57 +0200 Subject: [PATCH 201/396] drm/armada: Use drm_plane_helper_destroy() Replace the driver's own function with drm_plane_helper_destroy(). No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720083058.15371-7-tzimmermann@suse.de --- drivers/gpu/drm/armada/armada_overlay.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 1db77549189e..f21eb8fb76d8 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -9,6 +9,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_fourcc.h> +#include <drm/drm_plane_helper.h> #include "armada_crtc.h" #include "armada_drm.h" @@ -297,12 +298,6 @@ fail: return ret; } -static void armada_ovl_plane_destroy(struct drm_plane *plane) -{ - drm_plane_cleanup(plane); - kfree(plane); -} - static void armada_overlay_reset(struct drm_plane *plane) { struct armada_overlay_state *state; @@ -467,7 +462,7 @@ static int armada_overlay_get_property(struct drm_plane *plane, static const struct drm_plane_funcs armada_ovl_plane_funcs = { .update_plane = armada_overlay_plane_update, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = armada_ovl_plane_destroy, + .destroy = drm_plane_helper_destroy, .reset = armada_overlay_reset, .atomic_duplicate_state = armada_overlay_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, From a4d847df8b440cc667c18f99abe84ccaa83afac4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 20 Jul 2022 10:30:58 +0200 Subject: [PATCH 202/396] drm/fsl-dcu: Use drm_plane_helper_destroy() Replace the driver's own function with drm_plane_helper_destroy(). No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720083058.15371-8-tzimmermann@suse.de --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index e4f518e44945..3b20e79158c8 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -14,6 +14,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include "fsl_dcu_drm_drv.h" @@ -170,16 +171,10 @@ static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = { .atomic_update = fsl_dcu_drm_plane_atomic_update, }; -static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane) -{ - drm_plane_cleanup(plane); - kfree(plane); -} - static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = { .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, - .destroy = fsl_dcu_drm_plane_destroy, + .destroy = drm_plane_helper_destroy, .disable_plane = drm_atomic_helper_disable_plane, .reset = drm_atomic_helper_plane_reset, .update_plane = drm_atomic_helper_update_plane, From b320c7b7343885a346949abb56ea20528d611148 Mon Sep 17 00:00:00 2001 From: Slark Xiao <slark_xiao@163.com> Date: Thu, 21 Jul 2022 14:23:45 +0800 Subject: [PATCH 203/396] drm: Fix typo 'the the' in comment Replace 'the the' with 'the' in the comment. Signed-off-by: Slark Xiao <slark_xiao@163.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220721062345.46842-1-slark_xiao@163.com --- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/panel/panel-novatek-nt35510.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 73cebc6aa650..783a6ca41a61 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -65,7 +65,7 @@ /* * Interrupt statistic for PMU. Increments the counter only if the - * interrupt originated from the the GPU so interrupts from a device which + * interrupt originated from the GPU so interrupts from a device which * shares the interrupt line are not accounted. */ static inline void pmu_irq_stats(struct drm_i915_private *i915, diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index c613ad967ba6..493c3c23f0d6 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -231,7 +231,7 @@ struct nt35510_config { * bits 0..2 in the lower nibble controls HCK, the booster clock * frequency, the values are the same as for PCK in @bt1ctr. * bits 4..5 in the upper nibble controls BTH, the boosting - * amplification for the the step-up circuit. + * amplification for the step-up circuit. * 0 = AVDD + VDDB * 1 = AVDD - AVEE * 2 = AVDD - AVEE + VDDB From e6e627482a19a34b68116cdb5756bb199b5e2e52 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Mon, 25 Jul 2022 17:17:02 +0200 Subject: [PATCH 204/396] dt-bindings: display: panel: sitronix,st7701: Add Densitron DMT028VGHMCMI-1A TFT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add compatible string for Densitron DMT028VGHMCMI-1A TFT matrix. This is a DSI-attached 480x640 2.83 inch panel. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: devicetree@vger.kernel.org Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220725151703.319939-1-marex@denx.de --- .../devicetree/bindings/display/panel/sitronix,st7701.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml index 6dff59fe4be1..34d5e20c6cb3 100644 --- a/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml +++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml @@ -17,6 +17,9 @@ description: | Techstar TS8550B is 480x854, 2-lane MIPI DSI LCD panel which has inbuilt ST7701 chip. + Densitron DMT028VGHMCMI-1A is 480x640, 2-lane MIPI DSI LCD panel + which has built-in ST7701 chip. + allOf: - $ref: panel-common.yaml# @@ -24,6 +27,7 @@ properties: compatible: items: - enum: + - densitron,dmt028vghmcmi-1a - techstar,ts8550b - const: sitronix,st7701 From 57b2efce45ef5429e8d050190242849890b1fd96 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Mon, 25 Jul 2022 17:17:03 +0200 Subject: [PATCH 205/396] drm/panel/panel-sitronix-st7701: Add Densitron DMT028VGHMCMI-1A TFT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for Densitron DMT028VGHMCMI-1A TFT matrix into this driver. This is a DSI-attached 480x640 2.83 inch panel. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220725151703.319939-2-marex@denx.de --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 187 +++++++++++++++++- 1 file changed, 182 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 65ee383e62fd..c481daa4bbce 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -42,13 +42,16 @@ /* * Command2 with BK function selection. * - * BIT[4, 0]: [CN2, BKXSEL] - * 10 = CMD2BK0, Command2 BK0 - * 11 = CMD2BK1, Command2 BK1 - * 00 = Command2 disable + * BIT[4].....CN2 + * BIT[1:0]...BKXSEL + * 1:00 = CMD2BK0, Command2 BK0 + * 1:01 = CMD2BK1, Command2 BK1 + * 1:11 = CMD2BK3, Command2 BK3 + * 0:00 = Command2 disable */ -#define DSI_CMD2BK1_SEL 0x11 #define DSI_CMD2BK0_SEL 0x10 +#define DSI_CMD2BK1_SEL 0x11 +#define DSI_CMD2BK3_SEL 0x13 #define DSI_CMD2BKX_SEL_NONE 0x00 /* Command2, BK0 bytes */ @@ -329,6 +332,78 @@ static void ts8550b_gip_sequence(struct st7701 *st7701) 0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40, 0x1F, 0xFF); } +static void dmt028vghmcmi_1a_gip_sequence(struct st7701 *st7701) +{ + ST7701_DSI(st7701, 0xEE, 0x42); + ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02); + + ST7701_DSI(st7701, 0xE1, + 0x04, 0xA0, 0x06, 0xA0, + 0x05, 0xA0, 0x07, 0xA0, + 0x00, 0x44, 0x44); + ST7701_DSI(st7701, 0xE2, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + ST7701_DSI(st7701, 0xE3, + 0x00, 0x00, 0x22, 0x22); + ST7701_DSI(st7701, 0xE4, 0x44, 0x44); + ST7701_DSI(st7701, 0xE5, + 0x0C, 0x90, 0xA0, 0xA0, + 0x0E, 0x92, 0xA0, 0xA0, + 0x08, 0x8C, 0xA0, 0xA0, + 0x0A, 0x8E, 0xA0, 0xA0); + ST7701_DSI(st7701, 0xE6, + 0x00, 0x00, 0x22, 0x22); + ST7701_DSI(st7701, 0xE7, 0x44, 0x44); + ST7701_DSI(st7701, 0xE8, + 0x0D, 0x91, 0xA0, 0xA0, + 0x0F, 0x93, 0xA0, 0xA0, + 0x09, 0x8D, 0xA0, 0xA0, + 0x0B, 0x8F, 0xA0, 0xA0); + ST7701_DSI(st7701, 0xEB, + 0x00, 0x00, 0xE4, 0xE4, + 0x44, 0x00, 0x00); + ST7701_DSI(st7701, 0xED, + 0xFF, 0xF5, 0x47, 0x6F, + 0x0B, 0xA1, 0xAB, 0xFF, + 0xFF, 0xBA, 0x1A, 0xB0, + 0xF6, 0x74, 0x5F, 0xFF); + ST7701_DSI(st7701, 0xEF, + 0x08, 0x08, 0x08, 0x40, + 0x3F, 0x64); + + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, + 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE); + + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, + 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK3_SEL); + ST7701_DSI(st7701, 0xE6, 0x7C); + ST7701_DSI(st7701, 0xE8, 0x00, 0x0E); + + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, + 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE); + ST7701_DSI(st7701, 0x11); + msleep(120); + + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, + 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK3_SEL); + ST7701_DSI(st7701, 0xE8, 0x00, 0x0C); + msleep(10); + ST7701_DSI(st7701, 0xE8, 0x00, 0x00); + + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, + 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE); + ST7701_DSI(st7701, 0x11); + msleep(120); + ST7701_DSI(st7701, 0xE8, 0x00, 0x00); + + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, + 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE); + + ST7701_DSI(st7701, 0x3A, 0x70); +} + static int st7701_prepare(struct drm_panel *panel) { struct st7701 *st7701 = panel_to_st7701(panel); @@ -532,6 +607,107 @@ static const struct st7701_panel_desc ts8550b_desc = { .gip_sequence = ts8550b_gip_sequence, }; +static const struct drm_display_mode dmt028vghmcmi_1a_mode = { + .clock = 22325, + + .hdisplay = 480, + .hsync_start = 480 + 40, + .hsync_end = 480 + 40 + 4, + .htotal = 480 + 40 + 4 + 20, + + .vdisplay = 640, + .vsync_start = 640 + 2, + .vsync_end = 640 + 2 + 40, + .vtotal = 640 + 2 + 40 + 16, + + .width_mm = 56, + .height_mm = 78, + + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct st7701_panel_desc dmt028vghmcmi_1a_desc = { + .mode = &dmt028vghmcmi_1a_mode, + .lanes = 2, + .format = MIPI_DSI_FMT_RGB888, + .panel_sleep_delay = 5, /* panel need extra 5ms for sleep out cmd */ + + .pv_gamma = { + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0x10), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x17), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x5), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1f), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x29), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) + }, + .nv_gamma = { + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xe), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x4), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13), + + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x13), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x26), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30), + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) | + CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f) + }, + .nlinv = 1, + .vop_uv = 4800000, + .vcom_uv = 1650000, + .vgh_mv = 15000, + .vgl_mv = -10170, + .avdd_mv = 6600, + .avcl_mv = -4400, + .gamma_op_bias = OP_BIAS_MIDDLE, + .input_op_bias = OP_BIAS_MIN, + .output_op_bias = OP_BIAS_MIN, + .t2d_ns = 1600, + .t3d_ns = 10400, + .eot_en = true, + .gip_sequence = dmt028vghmcmi_1a_gip_sequence, +}; + static int st7701_dsi_probe(struct mipi_dsi_device *dsi) { const struct st7701_panel_desc *desc; @@ -598,6 +774,7 @@ static void st7701_dsi_remove(struct mipi_dsi_device *dsi) } static const struct of_device_id st7701_of_match[] = { + { .compatible = "densitron,dmt028vghmcmi-1a", .data = &dmt028vghmcmi_1a_desc }, { .compatible = "techstar,ts8550b", .data = &ts8550b_desc }, { } }; From 5727dcfd8486399c40e39d2c08fe36fedab29d99 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Mon, 25 Jul 2022 09:54:00 +0200 Subject: [PATCH 206/396] fbdev: Make registered_fb[] private to fbmem.c No driver access this anymore, except for the olpc dcon fbdev driver but that has been marked as broken anyways by commit de0952f267ff ("staging: olpc_dcon: mark driver as broken"). Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220725075400.68478-1-javierm@redhat.com --- drivers/video/fbdev/core/fbmem.c | 6 +++--- include/linux/fb.h | 6 ------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 6ae1c5fa19f9..1e70d8c67653 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -51,10 +51,10 @@ static DEFINE_MUTEX(registration_lock); struct fb_info *registered_fb[FB_MAX] __read_mostly; -EXPORT_SYMBOL(registered_fb); - int num_registered_fb __read_mostly; -EXPORT_SYMBOL(num_registered_fb); +#define for_each_registered_fb(i) \ + for (i = 0; i < FB_MAX; i++) \ + if (!registered_fb[i]) {} else bool fb_center_logo __read_mostly; diff --git a/include/linux/fb.h b/include/linux/fb.h index 453c3b2b6b8e..0aff76bcbb00 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -627,16 +627,10 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var, extern int fb_get_options(const char *name, char **option); extern int fb_new_modelist(struct fb_info *info); -extern struct fb_info *registered_fb[FB_MAX]; -extern int num_registered_fb; extern bool fb_center_logo; extern int fb_logo_count; extern struct class *fb_class; -#define for_each_registered_fb(i) \ - for (i = 0; i < FB_MAX; i++) \ - if (!registered_fb[i]) {} else - static inline void lock_fb_info(struct fb_info *info) { mutex_lock(&info->lock); From 2ddd1e6ccb139b9e7f1fed2883e34add832cbd77 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 20:52:54 +0200 Subject: [PATCH 207/396] drm/amdgpu: use idr_init_base() to initialize mgr->ctx_handles idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701185303.284082-2-dakr@redhat.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 2ef5296216d6..b212eaa280a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -842,7 +842,7 @@ void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr, mgr->adev = adev; mutex_init(&mgr->lock); - idr_init(&mgr->ctx_handles); + idr_init_base(&mgr->ctx_handles, 1); for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) atomic64_set(&mgr->time_spend[i], 0); From c4f306e31632e997c01f3e5ff3298ffc3a127999 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 20:52:55 +0200 Subject: [PATCH 208/396] drm/amdgpu: use idr_init_base() to initialize fpriv->bo_list_handles idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701185303.284082-3-dakr@redhat.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 6de63ea6687e..103927c48d05 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1148,7 +1148,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) } mutex_init(&fpriv->bo_list_lock); - idr_init(&fpriv->bo_list_handles); + idr_init_base(&fpriv->bo_list_handles, 1); amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev); From a49afeb4165361819b92b7991b97457bac4c674c Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 20:52:56 +0200 Subject: [PATCH 209/396] drm: use idr_init_base() to initialize master->magic_map idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701185303.284082-4-dakr@redhat.com --- drivers/gpu/drm/drm_auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 6e433d465f41..63395bebaa6b 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -140,7 +140,7 @@ struct drm_master *drm_master_create(struct drm_device *dev) kref_init(&master->refcount); drm_master_legacy_init(master); - idr_init(&master->magic_map); + idr_init_base(&master->magic_map, 1); master->dev = dev; /* initialize the tree of output resource lessees */ From 3a6acb7dd69f9d8960009ed1ceb77dc5e532391a Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 20:52:57 +0200 Subject: [PATCH 210/396] drm: use idr_init_base() to initialize master->lessee_idr idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701185303.284082-5-dakr@redhat.com --- drivers/gpu/drm/drm_auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 63395bebaa6b..cf92a9ae8034 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -147,7 +147,7 @@ struct drm_master *drm_master_create(struct drm_device *dev) INIT_LIST_HEAD(&master->lessees); INIT_LIST_HEAD(&master->lessee_list); idr_init(&master->leases); - idr_init(&master->lessee_idr); + idr_init_base(&master->lessee_idr, 1); return master; } From 1765378dfb10d4feedfc71cd721c4140d927c488 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 20:52:58 +0200 Subject: [PATCH 211/396] drm: use idr_init_base() to initialize mode_config.object_idr idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701185303.284082-6-dakr@redhat.com --- drivers/gpu/drm/drm_mode_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 59b34f07cfce..6d832277aa73 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -412,7 +412,7 @@ int drmm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.property_blob_list); INIT_LIST_HEAD(&dev->mode_config.plane_list); INIT_LIST_HEAD(&dev->mode_config.privobj_list); - idr_init(&dev->mode_config.object_idr); + idr_init_base(&dev->mode_config.object_idr, 1); idr_init(&dev->mode_config.tile_idr); ida_init(&dev->mode_config.connector_ida); spin_lock_init(&dev->mode_config.connector_list_lock); From 1d4f70a65fafb484064b9c7caa7318e9fd2ab737 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 20:52:59 +0200 Subject: [PATCH 212/396] drm: use idr_init_base() to initialize mode_config.tile_idr idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701185303.284082-7-dakr@redhat.com --- drivers/gpu/drm/drm_mode_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 6d832277aa73..688c8afe0bf1 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -413,7 +413,7 @@ int drmm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.plane_list); INIT_LIST_HEAD(&dev->mode_config.privobj_list); idr_init_base(&dev->mode_config.object_idr, 1); - idr_init(&dev->mode_config.tile_idr); + idr_init_base(&dev->mode_config.tile_idr, 1); ida_init(&dev->mode_config.connector_ida); spin_lock_init(&dev->mode_config.connector_list_lock); From bf8afc2090795b8640bf1842529627e69f673df4 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 20:53:00 +0200 Subject: [PATCH 213/396] drm/sis: use idr_init_base() to initialize dev_priv->object_idr idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701185303.284082-8-dakr@redhat.com --- drivers/gpu/drm/sis/sis_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index e35e719cf315..6173020a9bf5 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -50,7 +50,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv == NULL) return -ENOMEM; - idr_init(&dev_priv->object_idr); + idr_init_base(&dev_priv->object_idr, 1); dev->dev_private = (void *)dev_priv; dev_priv->chipset = chipset; From 604bda63bf939d6f5afef0b20d7ddee3abd27852 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 21:02:25 +0200 Subject: [PATCH 214/396] drm/v3d: use idr_init_base() to initialize v3d_priv->perfmon.idr idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701190227.284783-1-dakr@redhat.com --- drivers/gpu/drm/v3d/v3d_perfmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c index f6a88abccc7d..48aaaa972c49 100644 --- a/drivers/gpu/drm/v3d/v3d_perfmon.c +++ b/drivers/gpu/drm/v3d/v3d_perfmon.c @@ -95,7 +95,7 @@ struct v3d_perfmon *v3d_perfmon_find(struct v3d_file_priv *v3d_priv, int id) void v3d_perfmon_open_file(struct v3d_file_priv *v3d_priv) { mutex_init(&v3d_priv->perfmon.lock); - idr_init(&v3d_priv->perfmon.idr); + idr_init_base(&v3d_priv->perfmon.idr, 1); } static int v3d_perfmon_idr_del(int id, void *elem, void *data) From b765bc9968de022cc7dfc745d23de595fcc2b6cd Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 21:02:26 +0200 Subject: [PATCH 215/396] drm/via: use idr_init_base() to initialize dev_priv->object_idr idr_init_base(), implemented by commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient"), let us set an arbitrary base other than idr_init(), which uses base 0. Since, for this IDR, no ID < 1 is ever requested/allocated, using idr_init_base(&idr, 1) avoids unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701190227.284783-2-dakr@redhat.com --- drivers/gpu/drm/via/via_dri1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index d695d9291ece..f659c0c0465c 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -2846,7 +2846,7 @@ static int via_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv == NULL) return -ENOMEM; - idr_init(&dev_priv->object_idr); + idr_init_base(&dev_priv->object_idr, 1); dev->dev_private = (void *)dev_priv; dev_priv->chipset = chipset; From 8e61cbd483aee6ac6be9f5821e1bf22bed0710ff Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Fri, 1 Jul 2022 21:02:27 +0200 Subject: [PATCH 216/396] drm/todo: remove task for idr_init_base() All IDRs in the DRM core and drivers which are applicable for using idr_init_base() over idr_init() should be set up to use a proper base in order to avoid unnecessary tree walks. Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220701190227.284783-3-dakr@redhat.com --- Documentation/gpu/todo.rst | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 10bfb50908d1..de226ccc2c54 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -322,18 +322,6 @@ Contact: Daniel Vetter, Noralf Tronnes Level: Advanced -idr_init_base() ---------------- - -DRM core&drivers uses a lot of idr (integer lookup directories) for mapping -userspace IDs to internal objects, and in most places ID=0 means NULL and hence -is never used. Switching to idr_init_base() for these would make the idr more -efficient. - -Contact: Daniel Vetter - -Level: Starter - struct drm_gem_object_funcs --------------------------- From 18c8485236a5e3f491b670c018ae391c9cb84dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jose.exposito89@gmail.com> Date: Wed, 27 Jul 2022 01:09:13 +0200 Subject: [PATCH 217/396] drm/format-helper: Fix test on big endian architectures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests fail on big endian architectures, like PowerPC: $ ./tools/testing/kunit/kunit.py run \ --kunitconfig=drivers/gpu/drm/tests \ --arch=powerpc --cross_compile=powerpc64-linux-gnu- Transform the XRGB8888 buffer from little endian to the CPU endian before calling the conversion function to avoid this error. Fixes: 8f456104915f ("drm/format-helper: Add KUnit tests for drm_fb_xrgb8888_to_rgb332()") Reported-by: David Gow <davidgow@google.com> Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: José Expósito <jose.exposito89@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220726230916.390575-2-jose.exposito89@gmail.com --- .../gpu/drm/tests/drm_format_helper_test.c | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 98583bf56044..eefaba3aaea2 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -111,6 +111,21 @@ static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch, return dst_pitch * drm_rect_height(clip); } +static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size) +{ + u32 *dst = NULL; + int n; + + dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL); + if (!dst) + return NULL; + + for (n = 0; n < buf_size; n++) + dst[n] = le32_to_cpu((__force __le32)buf[n]); + + return dst; +} + static void xrgb8888_to_rgb332_case_desc(struct xrgb8888_to_rgb332_case *t, char *desc) { @@ -125,6 +140,7 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) const struct xrgb8888_to_rgb332_case *params = test->param_value; size_t dst_size; __u8 *dst = NULL; + __u32 *src = NULL; struct drm_framebuffer fb = { .format = drm_format_info(DRM_FORMAT_XRGB8888), @@ -138,8 +154,11 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) dst = kunit_kzalloc(test, dst_size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dst); - drm_fb_xrgb8888_to_rgb332(dst, params->dst_pitch, params->xrgb8888, - &fb, ¶ms->clip); + src = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, src); + + drm_fb_xrgb8888_to_rgb332(dst, params->dst_pitch, src, &fb, + ¶ms->clip); KUNIT_EXPECT_EQ(test, memcmp(dst, params->expected, dst_size), 0); } From 696560d43b4b07b58cf8604a9b186b32159164d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jose.exposito89@gmail.com> Date: Wed, 27 Jul 2022 01:09:14 +0200 Subject: [PATCH 218/396] drm/format-helper: Rename test cases to make them more generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests available at the moment only check the conversion from XRGB8888 to RGB332. However, more conversions will be tested in the future. In order to make the struct and functions present in the tests more generic, rename xrgb8888_to_rgb332_* to convert_xrgb8888_*. Tested-by: Tales L. Aparecida <tales.aparecida@gmail.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: José Expósito <jose.exposito89@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220726230916.390575-3-jose.exposito89@gmail.com --- drivers/gpu/drm/tests/drm_format_helper_test.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index eefaba3aaea2..97fccd0a948b 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -16,7 +16,7 @@ #define TEST_BUF_SIZE 50 -struct xrgb8888_to_rgb332_case { +struct convert_xrgb8888_case { const char *name; unsigned int pitch; unsigned int dst_pitch; @@ -25,7 +25,7 @@ struct xrgb8888_to_rgb332_case { const u8 expected[4 * TEST_BUF_SIZE]; }; -static struct xrgb8888_to_rgb332_case xrgb8888_to_rgb332_cases[] = { +static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { { .name = "single_pixel_source_buffer", .pitch = 1 * 4, @@ -126,18 +126,18 @@ static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size) return dst; } -static void xrgb8888_to_rgb332_case_desc(struct xrgb8888_to_rgb332_case *t, - char *desc) +static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t, + char *desc) { strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); } -KUNIT_ARRAY_PARAM(xrgb8888_to_rgb332, xrgb8888_to_rgb332_cases, - xrgb8888_to_rgb332_case_desc); +KUNIT_ARRAY_PARAM(convert_xrgb8888, convert_xrgb8888_cases, + convert_xrgb8888_case_desc); static void xrgb8888_to_rgb332_test(struct kunit *test) { - const struct xrgb8888_to_rgb332_case *params = test->param_value; + const struct convert_xrgb8888_case *params = test->param_value; size_t dst_size; __u8 *dst = NULL; __u32 *src = NULL; @@ -163,8 +163,7 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) } static struct kunit_case drm_format_helper_test_cases[] = { - KUNIT_CASE_PARAM(xrgb8888_to_rgb332_test, - xrgb8888_to_rgb332_gen_params), + KUNIT_CASE_PARAM(xrgb8888_to_rgb332_test, convert_xrgb8888_gen_params), {} }; From 4d09017aec4f2aa5f6109b32f9a037f35c17a9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jose.exposito89@gmail.com> Date: Wed, 27 Jul 2022 01:09:15 +0200 Subject: [PATCH 219/396] drm/format-helper: Support multiple target formats results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to support multiple destination format conversions, store the destination pitch and the expected result in its own structure. Tested-by: Tales L. Aparecida <tales.aparecida@gmail.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: José Expósito <jose.exposito89@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220726230916.390575-4-jose.exposito89@gmail.com --- .../gpu/drm/tests/drm_format_helper_test.c | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 97fccd0a948b..bbe9e9f57e2b 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -16,34 +16,42 @@ #define TEST_BUF_SIZE 50 +struct convert_to_rgb332_result { + unsigned int dst_pitch; + const u8 expected[TEST_BUF_SIZE]; +}; + struct convert_xrgb8888_case { const char *name; unsigned int pitch; - unsigned int dst_pitch; struct drm_rect clip; const u32 xrgb8888[TEST_BUF_SIZE]; - const u8 expected[4 * TEST_BUF_SIZE]; + struct convert_to_rgb332_result rgb332_result; }; static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { { .name = "single_pixel_source_buffer", .pitch = 1 * 4, - .dst_pitch = 0, .clip = DRM_RECT_INIT(0, 0, 1, 1), .xrgb8888 = { 0x01FF0000 }, - .expected = { 0xE0 }, + .rgb332_result = { + .dst_pitch = 0, + .expected = { 0xE0 }, + }, }, { .name = "single_pixel_clip_rectangle", .pitch = 2 * 4, - .dst_pitch = 0, .clip = DRM_RECT_INIT(1, 1, 1, 1), .xrgb8888 = { 0x00000000, 0x00000000, 0x00000000, 0x10FF0000, }, - .expected = { 0xE0 }, + .rgb332_result = { + .dst_pitch = 0, + .expected = { 0xE0 }, + }, }, { /* Well known colors: White, black, red, green, blue, magenta, @@ -52,7 +60,6 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { */ .name = "well_known_colors", .pitch = 4 * 4, - .dst_pitch = 0, .clip = DRM_RECT_INIT(1, 1, 2, 4), .xrgb8888 = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -61,28 +68,33 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0x00000000, 0x550000FF, 0x66FF00FF, 0x00000000, 0x00000000, 0x77FFFF00, 0x8800FFFF, 0x00000000, }, - .expected = { - 0xFF, 0x00, - 0xE0, 0x1C, - 0x03, 0xE3, - 0xFC, 0x1F, + .rgb332_result = { + .dst_pitch = 0, + .expected = { + 0xFF, 0x00, + 0xE0, 0x1C, + 0x03, 0xE3, + 0xFC, 0x1F, + }, }, }, { /* Randomly picked colors. Full buffer within the clip area. */ .name = "destination_pitch", .pitch = 3 * 4, - .dst_pitch = 5, .clip = DRM_RECT_INIT(0, 0, 3, 3), .xrgb8888 = { 0xA10E449C, 0xB1114D05, 0xC1A80303, 0xD16C7073, 0xA20E449C, 0xB2114D05, 0xC2A80303, 0xD26C7073, 0xA30E449C, }, - .expected = { - 0x0A, 0x08, 0xA0, 0x00, 0x00, - 0x6D, 0x0A, 0x08, 0x00, 0x00, - 0xA0, 0x6D, 0x0A, 0x00, 0x00, + .rgb332_result = { + .dst_pitch = 5, + .expected = { + 0x0A, 0x08, 0xA0, 0x00, 0x00, + 0x6D, 0x0A, 0x08, 0x00, 0x00, + 0xA0, 0x6D, 0x0A, 0x00, 0x00, + }, }, }, }; @@ -138,6 +150,7 @@ KUNIT_ARRAY_PARAM(convert_xrgb8888, convert_xrgb8888_cases, static void xrgb8888_to_rgb332_test(struct kunit *test) { const struct convert_xrgb8888_case *params = test->param_value; + const struct convert_to_rgb332_result *result = ¶ms->rgb332_result; size_t dst_size; __u8 *dst = NULL; __u32 *src = NULL; @@ -147,7 +160,7 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) .pitches = { params->pitch, 0, 0 }, }; - dst_size = conversion_buf_size(DRM_FORMAT_RGB332, params->dst_pitch, + dst_size = conversion_buf_size(DRM_FORMAT_RGB332, result->dst_pitch, ¶ms->clip); KUNIT_ASSERT_GT(test, dst_size, 0); @@ -157,9 +170,9 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) src = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, src); - drm_fb_xrgb8888_to_rgb332(dst, params->dst_pitch, src, &fb, + drm_fb_xrgb8888_to_rgb332(dst, result->dst_pitch, src, &fb, ¶ms->clip); - KUNIT_EXPECT_EQ(test, memcmp(dst, params->expected, dst_size), 0); + KUNIT_EXPECT_EQ(test, memcmp(dst, result->expected, dst_size), 0); } static struct kunit_case drm_format_helper_test_cases[] = { From 5d2f2e8b3a36328a3981996bb20c32d8a0e53b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jose.exposito89@gmail.com> Date: Wed, 27 Jul 2022 01:09:16 +0200 Subject: [PATCH 220/396] drm/format-helper: Add KUnit tests for drm_fb_xrgb8888_to_rgb565() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend the existing test cases to test the conversion from XRGB8888 to RGB565. The documentation and the color picker available on [1] are useful resources to understand this patch and validate the values returned by the conversion function. Tested-by: Tales L. Aparecida <tales.aparecida@gmail.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: José Expósito <jose.exposito89@gmail.com> Link: http://www.barth-dev.de/online/rgb565-color-picker/ # [1] Link: https://patchwork.freedesktop.org/patch/msgid/20220726230916.390575-5-jose.exposito89@gmail.com --- .../gpu/drm/tests/drm_format_helper_test.c | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index bbe9e9f57e2b..26ecf3b4b137 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -21,12 +21,19 @@ struct convert_to_rgb332_result { const u8 expected[TEST_BUF_SIZE]; }; +struct convert_to_rgb565_result { + unsigned int dst_pitch; + const u16 expected[TEST_BUF_SIZE]; + const u16 expected_swab[TEST_BUF_SIZE]; +}; + struct convert_xrgb8888_case { const char *name; unsigned int pitch; struct drm_rect clip; const u32 xrgb8888[TEST_BUF_SIZE]; struct convert_to_rgb332_result rgb332_result; + struct convert_to_rgb565_result rgb565_result; }; static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { @@ -39,6 +46,11 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = 0, .expected = { 0xE0 }, }, + .rgb565_result = { + .dst_pitch = 0, + .expected = { 0xF800 }, + .expected_swab = { 0x00F8 }, + }, }, { .name = "single_pixel_clip_rectangle", @@ -52,6 +64,11 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = 0, .expected = { 0xE0 }, }, + .rgb565_result = { + .dst_pitch = 0, + .expected = { 0xF800 }, + .expected_swab = { 0x00F8 }, + }, }, { /* Well known colors: White, black, red, green, blue, magenta, @@ -77,6 +94,21 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0xFC, 0x1F, }, }, + .rgb565_result = { + .dst_pitch = 0, + .expected = { + 0xFFFF, 0x0000, + 0xF800, 0x07E0, + 0x001F, 0xF81F, + 0xFFE0, 0x07FF, + }, + .expected_swab = { + 0xFFFF, 0x0000, + 0x00F8, 0xE007, + 0x1F00, 0x1FF8, + 0xE0FF, 0xFF07, + }, + }, }, { /* Randomly picked colors. Full buffer within the clip area. */ @@ -96,6 +128,19 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0xA0, 0x6D, 0x0A, 0x00, 0x00, }, }, + .rgb565_result = { + .dst_pitch = 10, + .expected = { + 0x0A33, 0x1260, 0xA800, 0x0000, 0x0000, + 0x6B8E, 0x0A33, 0x1260, 0x0000, 0x0000, + 0xA800, 0x6B8E, 0x0A33, 0x0000, 0x0000, + }, + .expected_swab = { + 0x330A, 0x6012, 0x00A8, 0x0000, 0x0000, + 0x8E6B, 0x330A, 0x6012, 0x0000, 0x0000, + 0x00A8, 0x8E6B, 0x330A, 0x0000, 0x0000, + }, + }, }, }; @@ -175,8 +220,41 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) KUNIT_EXPECT_EQ(test, memcmp(dst, result->expected, dst_size), 0); } +static void xrgb8888_to_rgb565_test(struct kunit *test) +{ + const struct convert_xrgb8888_case *params = test->param_value; + const struct convert_to_rgb565_result *result = ¶ms->rgb565_result; + size_t dst_size; + __u16 *dst = NULL; + __u32 *src = NULL; + + struct drm_framebuffer fb = { + .format = drm_format_info(DRM_FORMAT_XRGB8888), + .pitches = { params->pitch, 0, 0 }, + }; + + dst_size = conversion_buf_size(DRM_FORMAT_RGB565, result->dst_pitch, + ¶ms->clip); + KUNIT_ASSERT_GT(test, dst_size, 0); + + dst = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dst); + + src = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, src); + + drm_fb_xrgb8888_to_rgb565(dst, result->dst_pitch, src, &fb, + ¶ms->clip, false); + KUNIT_EXPECT_EQ(test, memcmp(dst, result->expected, dst_size), 0); + + drm_fb_xrgb8888_to_rgb565(dst, result->dst_pitch, src, &fb, + ¶ms->clip, true); + KUNIT_EXPECT_EQ(test, memcmp(dst, result->expected_swab, dst_size), 0); +} + static struct kunit_case drm_format_helper_test_cases[] = { KUNIT_CASE_PARAM(xrgb8888_to_rgb332_test, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(xrgb8888_to_rgb565_test, convert_xrgb8888_gen_params), {} }; From 2ac6cdd581f48c8f68747156fde5868486a44985 Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Thu, 10 Feb 2022 15:40:25 +0000 Subject: [PATCH 221/396] drm/dp_mst: fix drm_dp_dpcd_read return value checks drm_dp_dpcd_read returns the number of bytes read. The previous code would print garbage on DPCD error, and would exit with on error on success. Signed-off-by: Simon Ser <contact@emersion.fr> Fixes: cb897542c6d2 ("drm/dp_mst: Fix W=1 warnings") Cc: Lyude Paul <lyude@redhat.com> Cc: Benjamin Gaignard <benjamin.gaignard@st.com> Reviewed-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/473500/ --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 57e65423e50d..7a94a5288e8d 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4907,14 +4907,14 @@ void drm_dp_mst_dump_topology(struct seq_file *m, seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf); ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2); - if (ret) { + if (ret != 2) { seq_printf(m, "faux/mst read failed\n"); goto out; } seq_printf(m, "faux/mst: %*ph\n", 2, buf); ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1); - if (ret) { + if (ret != 1) { seq_printf(m, "mst ctrl read failed\n"); goto out; } @@ -4922,7 +4922,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m, /* dump the standard OUI branch header */ ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE); - if (ret) { + if (ret != DP_BRANCH_OUI_HEADER_SIZE) { seq_printf(m, "branch oui read failed\n"); goto out; } From cf1e6a90315a3f5b8ecbb3cf6a4badf8978e9075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <mairacanal@riseup.net> Date: Fri, 29 Jul 2022 09:47:26 -0300 Subject: [PATCH 222/396] drm/tests: Split up test cases in igt_check_drm_format_min_pitch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The igt_check_drm_format_min_pitch() function had a lot of KUNIT_EXPECT_* calls, all of which ended up allocating and initializing various test assertion structures on the stack. This behavior was producing -Wframe-larger-than warnings on PowerPC, i386, and MIPS architectures, such as: drivers/gpu/drm/tests/drm_format_test.c: In function 'igt_check_drm_format_min_pitch': drivers/gpu/drm/tests/drm_format_test.c:271:1: error: the frame size of 3712 bytes is larger than 2048 bytes So, the igt_check_drm_format_min_pitch() test case was split into three smaller functions: one testing single plane formats, one testing multi-planar formats, and the other testing tiled formats. Fixes: 0421bb0baa84 ("drm: selftest: convert drm_format selftest to KUnit") Reported-by: kernel test robot <lkp@intel.com> Reported-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Maíra Canal <mairacanal@riseup.net> Tested-by: Guenter Roeck <linux@roeck-us.net> Reviewed-by: André Almeida <andrealmeid@igalia.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220729124726.748221-1-mairacanal@riseup.net --- drivers/gpu/drm/tests/drm_format_test.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c index 056cb8599d6d..afb4bca72187 100644 --- a/drivers/gpu/drm/tests/drm_format_test.c +++ b/drivers/gpu/drm/tests/drm_format_test.c @@ -91,7 +91,7 @@ static void igt_check_drm_format_block_height(struct kunit *test) KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); } -static void igt_check_drm_format_min_pitch(struct kunit *test) +static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test) { const struct drm_format_info *info = NULL; @@ -175,6 +175,11 @@ static void igt_check_drm_format_min_pitch(struct kunit *test) (uint64_t)UINT_MAX * 4); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)), (uint64_t)(UINT_MAX - 1) * 4); +} + +static void igt_check_drm_format_min_pitch_for_multi_planar(struct kunit *test) +{ + const struct drm_format_info *info = NULL; /* Test 2 planes format */ info = drm_format_info(DRM_FORMAT_NV12); @@ -249,6 +254,11 @@ static void igt_check_drm_format_min_pitch(struct kunit *test) (uint64_t)(UINT_MAX - 1) / 2); KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2), (uint64_t)(UINT_MAX - 1) / 2); +} + +static void igt_check_drm_format_min_pitch_for_tiled_format(struct kunit *test) +{ + const struct drm_format_info *info = NULL; /* Test tiled format */ info = drm_format_info(DRM_FORMAT_X0L2); @@ -273,7 +283,9 @@ static void igt_check_drm_format_min_pitch(struct kunit *test) static struct kunit_case drm_format_tests[] = { KUNIT_CASE(igt_check_drm_format_block_width), KUNIT_CASE(igt_check_drm_format_block_height), - KUNIT_CASE(igt_check_drm_format_min_pitch), + KUNIT_CASE(igt_check_drm_format_min_pitch_for_single_plane), + KUNIT_CASE(igt_check_drm_format_min_pitch_for_multi_planar), + KUNIT_CASE(igt_check_drm_format_min_pitch_for_tiled_format), { } }; From 44373151ab429cca53fae53d9eed374aef64afad Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:50 +0200 Subject: [PATCH 223/396] drm/mgag200: Split mgag200_modeset_init() Split mgag200_modeset_init() into smaller helpers to initialize the mode_config structure and the pipeline. This will be helpful for transforming this code into per-model functions. No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-2-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_mode.c | 41 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a02f599cb9cf..78fdb3148ed7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1047,23 +1047,16 @@ static const struct drm_mode_config_funcs mgag200_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available) +static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available) { struct drm_device *dev = &mdev->base; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; - struct drm_simple_display_pipe *pipe = &mdev->display_pipe; - size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats); int ret; - mgag200_init_regs(mdev); - mdev->vram_available = vram_available; ret = drmm_mode_config_init(dev); if (ret) { - drm_err(dev, "drmm_mode_config_init() failed, error %d\n", - ret); + drm_err(dev, "drmm_mode_config_init() failed: %d\n", ret); return ret; } @@ -1073,6 +1066,18 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available dev->mode_config.fb_base = mdev->vram_res->start; dev->mode_config.funcs = &mgag200_mode_config_funcs; + return 0; +} + +static int mgag200_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + struct drm_simple_display_pipe *pipe = &mdev->display_pipe; + size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats); + int ret; + ret = mgag200_i2c_init(mdev, i2c); if (ret) { drm_err(dev, "failed to add DDC bus: %d\n", ret); @@ -1113,6 +1118,24 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available drm_crtc_enable_color_mgmt(&pipe->crtc, 0, false, MGAG200_LUT_SIZE); + return 0; +} + +int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available) +{ + struct drm_device *dev = &mdev->base; + int ret; + + mgag200_init_regs(mdev); + + ret = mgag200_mode_config_init(mdev, vram_available); + if (ret) + return ret; + + ret = mgag200_pipeline_init(mdev); + if (ret) + return ret; + drm_mode_config_reset(dev); return 0; From 1ee181fe958a11d023fd992b8eabe6d4287661ee Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:51 +0200 Subject: [PATCH 224/396] drm/mgag200: Move DAC-register setup into model-specific code Provide an init function for each model's DAC registers. Remove the shared helper. The code for initializing the DAC registers consisted of a large table of default value, plus many exceptions for the various G200 models. Providing a per-model implementation makes if more readable. At some point, some of the initialization should probably move into the modesetting code. v2: * don't duplicate DAC values unnecessarily (Sam, Jocelyn) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-3-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.h | 30 +++++++++ drivers/gpu/drm/mgag200/mgag200_g200.c | 25 +++++++ drivers/gpu/drm/mgag200/mgag200_g200eh.c | 26 ++++++++ drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 2 + drivers/gpu/drm/mgag200/mgag200_g200er.c | 25 +++++++ drivers/gpu/drm/mgag200/mgag200_g200ev.c | 27 ++++++++ drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 2 + drivers/gpu/drm/mgag200/mgag200_g200se.c | 30 +++++++++ drivers/gpu/drm/mgag200/mgag200_g200wb.c | 24 +++++++ drivers/gpu/drm/mgag200/mgag200_mode.c | 80 +---------------------- 10 files changed, 192 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 301c4ab46539..face2904556a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -123,6 +123,33 @@ #define MGA_MISC_OUT 0x1fc2 #define MGA_MISC_IN 0x1fcc +/* + * TODO: This is a pretty large set of default values for all kinds of + * settings. It should be split and set in the various DRM helpers, + * such as the CRTC reset or atomic_enable helpers. The PLL values + * probably belong to each model's PLL code. + */ +#define MGAG200_DAC_DEFAULT(xvrefctrl, xpixclkctrl, xmiscctrl, xsyspllm, xsysplln, xsyspllp) \ + /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, \ + /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, \ + /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, \ + /* 0x18: */ (xvrefctrl), \ + /* 0x19: */ 0, \ + /* 0x1a: */ (xpixclkctrl), \ + /* 0x1b: */ 0xff, 0xbf, 0x20, \ + /* 0x1e: */ (xmiscctrl), \ + /* 0x1f: */ 0x20, \ + /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + /* 0x28: */ 0x00, 0x00, 0x00, 0x00, \ + /* 0x2c: */ (xsyspllm), \ + /* 0x2d: */ (xsysplln), \ + /* 0x2e: */ (xsyspllp), \ + /* 0x2f: */ 0x40, \ + /* 0x30: */ 0x00, 0xb0, 0x00, 0xc2, 0x34, 0x14, 0x02, 0x83, \ + /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3a, \ + /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, \ + /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 \ + #define MGAG200_MAX_FB_HEIGHT 4096 #define MGAG200_MAX_FB_WIDTH 4096 @@ -295,10 +322,12 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct enum mga_type type); struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); +void mgag200_g200wb_init_registers(struct mga_device *mdev); struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); +void mgag200_g200eh_init_registers(struct mga_device *mdev); struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv, @@ -310,6 +339,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const str /* mgag200_mode.c */ resource_size_t mgag200_device_probe_vram(struct mga_device *mdev); +void mgag200_init_registers(struct mga_device *mdev); int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available); /* mgag200_i2c.c */ diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c index 674385921b7f..4a5af20efa36 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c @@ -30,6 +30,29 @@ static int mgag200_g200_init_pci_options(struct pci_dev *pdev) return mgag200_init_pci_options(pdev, option, 0x00008000); } +static void mgag200_g200_init_registers(struct mgag200_g200_device *g200) +{ + static const u8 dacvalue[] = { + MGAG200_DAC_DEFAULT(0x00, 0xc9, 0x1f, + 0x04, 0x2d, 0x19) + }; + + struct mga_device *mdev = &g200->base; + size_t i; + + for (i = 0; i < ARRAY_SIZE(dacvalue); ++i) { + if ((i <= 0x17) || + (i == 0x1b) || + (i == 0x1c) || + ((i >= 0x1f) && (i <= 0x29)) || + ((i >= 0x30) && (i <= 0x37))) + continue; + WREG_DAC(i, dacvalue[i]); + } + + mgag200_init_registers(mdev); +} + /* * DRM Device */ @@ -191,6 +214,8 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct if (ret) return ERR_PTR(ret); + mgag200_g200_init_registers(g200); + vram_available = mgag200_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c index 1b9a22728744..f2c53fe8d927 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c @@ -6,6 +6,30 @@ #include "mgag200_drv.h" +void mgag200_g200eh_init_registers(struct mga_device *mdev) +{ + static const u8 dacvalue[] = { + MGAG200_DAC_DEFAULT(0x00, 0xc9, + MGA1064_MISC_CTL_VGA8 | MGA1064_MISC_CTL_DAC_RAM_CS, + 0x00, 0x00, 0x00) + }; + + size_t i; + + for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { + if ((i <= 0x17) || + (i == 0x1b) || + (i == 0x1c) || + ((i >= 0x1f) && (i <= 0x29)) || + ((i >= 0x30) && (i <= 0x37)) || + ((i >= 0x44) && (i <= 0x4e))) + continue; + WREG_DAC(i, dacvalue[i]); + } + + mgag200_init_registers(mdev); +} + /* * DRM device */ @@ -40,6 +64,8 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); + mgag200_g200eh_init_registers(mdev); + vram_available = mgag200_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c index 438cda1b14c9..adb9190b62af 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c @@ -41,6 +41,8 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, if (ret) return ERR_PTR(ret); + mgag200_g200eh_init_registers(mdev); // same as G200EH + vram_available = mgag200_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 0790d4e6463d..7bee20459ab6 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -6,6 +6,29 @@ #include "mgag200_drv.h" +static void mgag200_g200er_init_registers(struct mga_device *mdev) +{ + static const u8 dacvalue[] = { + MGAG200_DAC_DEFAULT(0x00, 0xc9, 0x1f, 0x00, 0x00, 0x00) + }; + + size_t i; + + for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { + if ((i <= 0x17) || + (i == 0x1b) || + (i == 0x1c) || + ((i >= 0x1f) && (i <= 0x29)) || + ((i >= 0x30) && (i <= 0x37))) + continue; + WREG_DAC(i, dacvalue[i]); + } + + WREG_DAC(0x90, 0); /* G200ER specific */ + + mgag200_init_registers(mdev); +} + /* * DRM device */ @@ -36,6 +59,8 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); + mgag200_g200er_init_registers(mdev); + vram_available = mgag200_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index 5353422d0eef..0dc5c342e7c4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -6,6 +6,31 @@ #include "mgag200_drv.h" +static void mgag200_g200ev_init_registers(struct mga_device *mdev) +{ + static const u8 dacvalue[] = { + MGAG200_DAC_DEFAULT(0x00, + MGA1064_PIX_CLK_CTL_SEL_PLL, + MGA1064_MISC_CTL_VGA8 | MGA1064_MISC_CTL_DAC_RAM_CS, + 0x00, 0x00, 0x00) + }; + + size_t i; + + for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { + if ((i <= 0x17) || + (i == 0x1b) || + (i == 0x1c) || + ((i >= 0x1f) && (i <= 0x29)) || + ((i >= 0x30) && (i <= 0x37)) || + ((i >= 0x44) && (i <= 0x4e))) + continue; + WREG_DAC(i, dacvalue[i]); + } + + mgag200_init_registers(mdev); +} + /* * DRM device */ @@ -40,6 +65,8 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); + mgag200_g200ev_init_registers(mdev); + vram_available = mgag200_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index 3bfc1324cf78..d86284c0eb4d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -50,6 +50,8 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, if (ret) return ERR_PTR(ret); + mgag200_g200wb_init_registers(mdev); // same as G200WB + vram_available = mgag200_g200ew3_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index 0a3e66695e22..bd8fc7a177c2 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -28,6 +28,34 @@ static int mgag200_g200se_init_pci_options(struct pci_dev *pdev) return mgag200_init_pci_options(pdev, option, 0x00008000); } +static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se) +{ + static const u8 dacvalue[] = { + MGAG200_DAC_DEFAULT(0x03, + MGA1064_PIX_CLK_CTL_SEL_PLL, + MGA1064_MISC_CTL_DAC_EN | + MGA1064_MISC_CTL_VGA8 | + MGA1064_MISC_CTL_DAC_RAM_CS, + 0x00, 0x00, 0x00) + }; + + struct mga_device *mdev = &g200se->base; + size_t i; + + for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { + if ((i <= 0x17) || + (i == 0x1b) || + (i == 0x1c) || + ((i >= 0x1f) && (i <= 0x29)) || + ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)) || + ((i >= 0x30) && (i <= 0x37))) + continue; + WREG_DAC(i, dacvalue[i]); + } + + mgag200_init_registers(mdev); +} + /* * DRM device */ @@ -120,6 +148,8 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); + mgag200_g200se_init_registers(g200se); + vram_available = mgag200_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index c8450ac8eaec..05f17986b95a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -6,6 +6,28 @@ #include "mgag200_drv.h" +void mgag200_g200wb_init_registers(struct mga_device *mdev) +{ + static const u8 dacvalue[] = { + MGAG200_DAC_DEFAULT(0x07, 0xc9, 0x1f, 0x00, 0x00, 0x00) + }; + + size_t i; + + for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { + if ((i <= 0x17) || + (i == 0x1b) || + (i == 0x1c) || + ((i >= 0x1f) && (i <= 0x29)) || + ((i >= 0x30) && (i <= 0x37)) || + ((i >= 0x44) && (i <= 0x4e))) + continue; + WREG_DAC(i, dacvalue[i]); + } + + mgag200_init_registers(mdev); +} + /* * DRM device */ @@ -40,6 +62,8 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); + mgag200_g200wb_init_registers(mdev); + vram_available = mgag200_device_probe_vram(mdev); ret = mgag200_modeset_init(mdev, vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 78fdb3148ed7..ba5661cc6686 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -266,86 +266,10 @@ static void mgag200_set_startadd(struct mga_device *mdev, WREG_ECRT(0x00, crtcext0); } -static void mgag200_set_dac_regs(struct mga_device *mdev) -{ - size_t i; - u8 dacvalue[] = { - /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, - /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20, - /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40, - /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83, - /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A, - /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 - }; - - switch (mdev->type) { - case G200_PCI: - case G200_AGP: - dacvalue[MGA1064_SYS_PLL_M] = 0x04; - dacvalue[MGA1064_SYS_PLL_N] = 0x2D; - dacvalue[MGA1064_SYS_PLL_P] = 0x19; - break; - case G200_SE_A: - case G200_SE_B: - dacvalue[MGA1064_VREF_CTL] = 0x03; - dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL; - dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN | - MGA1064_MISC_CTL_VGA8 | - MGA1064_MISC_CTL_DAC_RAM_CS; - break; - case G200_WB: - case G200_EW3: - dacvalue[MGA1064_VREF_CTL] = 0x07; - break; - case G200_EV: - dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL; - dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 | - MGA1064_MISC_CTL_DAC_RAM_CS; - break; - case G200_EH: - case G200_EH3: - dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 | - MGA1064_MISC_CTL_DAC_RAM_CS; - break; - case G200_ER: - break; - } - - for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { - if ((i <= 0x17) || - (i == 0x1b) || - (i == 0x1c) || - ((i >= 0x1f) && (i <= 0x29)) || - ((i >= 0x30) && (i <= 0x37))) - continue; - if (IS_G200_SE(mdev) && - ((i == 0x2c) || (i == 0x2d) || (i == 0x2e))) - continue; - if ((mdev->type == G200_EV || - mdev->type == G200_WB || - mdev->type == G200_EH || - mdev->type == G200_EW3 || - mdev->type == G200_EH3) && - (i >= 0x44) && (i <= 0x4e)) - continue; - - WREG_DAC(i, dacvalue[i]); - } - - if (mdev->type == G200_ER) - WREG_DAC(0x90, 0); -} - -static void mgag200_init_regs(struct mga_device *mdev) +void mgag200_init_registers(struct mga_device *mdev) { u8 crtc11, misc; - mgag200_set_dac_regs(mdev); - WREG_SEQ(2, 0x0f); WREG_SEQ(3, 0x00); WREG_SEQ(4, 0x0e); @@ -1126,8 +1050,6 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available struct drm_device *dev = &mdev->base; int ret; - mgag200_init_regs(mdev); - ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ret; From 9382ec27acb2f5a43dc3c3b77036f898a498ba60 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:52 +0200 Subject: [PATCH 225/396] drm/mgag200: Move ER/EW3 register initialization to per-model code The register initialization code contains special cases for G200ER and G200EW3 hardware. Move this to per-model code. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-4-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_g200er.c | 2 ++ drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 9 ++++++++- drivers/gpu/drm/mgag200/mgag200_mode.c | 6 ------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 7bee20459ab6..8ff050906e1c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -27,6 +27,8 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev) WREG_DAC(0x90, 0); /* G200ER specific */ mgag200_init_registers(mdev); + + WREG_ECRT(0x24, 0x5); /* G200ER specific */ } /* diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index d86284c0eb4d..a4ecdd3784a3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -6,6 +6,13 @@ #include "mgag200_drv.h" +static void mgag200_g200ew3_init_registers(struct mga_device *mdev) +{ + mgag200_g200wb_init_registers(mdev); // same as G200WB + + WREG_ECRT(0x34, 0x5); // G200EW3 specific +} + /* * DRM device */ @@ -50,7 +57,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, if (ret) return ERR_PTR(ret); - mgag200_g200wb_init_registers(mdev); // same as G200WB + mgag200_g200ew3_init_registers(mdev); vram_available = mgag200_g200ew3_device_probe_vram(mdev); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index ba5661cc6686..11a88ef9d664 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -287,12 +287,6 @@ void mgag200_init_registers(struct mga_device *mdev) MGAREG_CRTC11_VINTCLR); WREG_CRT(0x11, crtc11); - if (mdev->type == G200_ER) - WREG_ECRT(0x24, 0x5); - - if (mdev->type == G200_EW3) - WREG_ECRT(0x34, 0x5); - misc = RREG8(MGA_MISC_IN); misc |= MGAREG_MISC_IOADSEL; WREG8(MGA_MISC_OUT, misc); From 2d70b9a1482e09f8465452c4655ffe20c605d526 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:53 +0200 Subject: [PATCH 226/396] drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function Hold I/O-register lock in atomic_commit_tail to protect all pipeline updates at once. Protects against concurrent I/O access in get-modes helper. Complex modesetting operations involve mode changes, plane updates and possibly BMC updates. Make all this atomic wrt to reading display modes via EDID. It's not so much an issue with simple-KMS helpers, but will become necessary for using regular atomic helpers. v4: * remove empty line Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-5-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_mode.c | 35 +++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 11a88ef9d664..6635d8745851 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/iosys-map.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_crtc_helper.h> @@ -702,14 +703,6 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, .y2 = fb->height, }; - /* - * Concurrent operations could possibly trigger a call to - * drm_connector_helper_funcs.get_modes by trying to read the - * display modes. Protect access to I/O registers by acquiring - * the I/O-register lock. - */ - mutex_lock(&mdev->rmmio_lock); - if (mdev->type == G200_WB || mdev->type == G200_EW3) mgag200_g200wb_hold_bmc(mdev); @@ -741,8 +734,6 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, /* Always scanout image at VRAM offset 0 */ mgag200_set_startadd(mdev, (u32)0); mgag200_set_offset(mdev, fb); - - mutex_unlock(&mdev->rmmio_lock); } static void @@ -812,8 +803,6 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, if (!fb) return; - mutex_lock(&mdev->rmmio_lock); - if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut) mgag200_crtc_set_gamma(mdev, fb->format, crtc->state->gamma_lut->data); @@ -824,8 +813,6 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, /* Always scanout image at VRAM offset 0 */ mgag200_set_startadd(mdev, (u32)0); mgag200_set_offset(mdev, fb); - - mutex_unlock(&mdev->rmmio_lock); } static struct drm_crtc_state * @@ -903,6 +890,25 @@ static const uint64_t mgag200_simple_display_pipe_fmtmods[] = { * Mode config */ +static void mgag200_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state) +{ + struct mga_device *mdev = to_mga_device(state->dev); + + /* + * Concurrent operations could possibly trigger a call to + * drm_connector_helper_funcs.get_modes by trying to read the + * display modes. Protect access to I/O registers by acquiring + * the I/O-register lock. + */ + mutex_lock(&mdev->rmmio_lock); + drm_atomic_helper_commit_tail(state); + mutex_unlock(&mdev->rmmio_lock); +} + +static const struct drm_mode_config_helper_funcs mgag200_mode_config_helper_funcs = { + .atomic_commit_tail = mgag200_mode_config_helper_atomic_commit_tail, +}; + /* Calculates a mode's required memory bandwidth (in KiB/sec). */ static uint32_t mgag200_calculate_mode_bandwidth(const struct drm_display_mode *mode, unsigned int bits_per_pixel) @@ -983,6 +989,7 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra dev->mode_config.preferred_depth = 24; dev->mode_config.fb_base = mdev->vram_res->start; dev->mode_config.funcs = &mgag200_mode_config_funcs; + dev->mode_config.helper_private = &mgag200_mode_config_helper_funcs; return 0; } From ed2ef21f1089ef9b3b943b4e365600e615ce827d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:54 +0200 Subject: [PATCH 227/396] drm/mgag200: Store primary plane's color format in CRTC state Store the primary plane's color format in the CRTC state and use it for programming the CRTC's gamma LUTs. Gamma tables (i.e., color management) are provided by the CRTC, but depend in the primary plane's color format. Store the format in the CRTC state and use it. This has not been an issue with simple-KMS helpers, which mix-up plane and CRTC state to some extent. For using regular atomic helpers, it's necessary to distinguish between the two. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-6-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.h | 3 +++ drivers/gpu/drm/mgag200/mgag200_mode.c | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index face2904556a..bf6a01ff9719 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -187,6 +187,9 @@ struct mgag200_pll { struct mgag200_crtc_state { struct drm_crtc_state base; + /* Primary-plane format; required for modesetting and color mgmt. */ + const struct drm_format_info *format; + struct mgag200_pll_values pixpllc; }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 6635d8745851..e392e2646359 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -418,11 +418,9 @@ static void mgag200_set_offset(struct mga_device *mdev, WREG_ECRT(0x00, crtcext0); } -static void mgag200_set_format_regs(struct mga_device *mdev, - const struct drm_framebuffer *fb) +static void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format) { struct drm_device *dev = &mdev->base; - const struct drm_format_info *format = fb->format; unsigned int bpp, bppshift, scale; u8 crtcext3, xmulctrl; @@ -501,7 +499,7 @@ static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev) static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, const struct drm_display_mode *mode, - const struct drm_framebuffer *fb) + const struct drm_format_info *format) { struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base); unsigned int hiprilvl; @@ -513,9 +511,9 @@ static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, unsigned int bpp; unsigned long mb; - if (fb->format->cpp[0] * 8 > 16) + if (format->cpp[0] * 8 > 16) bpp = 32; - else if (fb->format->cpp[0] * 8 > 8) + else if (format->cpp[0] * 8 > 8) bpp = 16; else bpp = 8; @@ -695,6 +693,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); struct drm_framebuffer *fb = plane_state->fb; + const struct drm_format_info *format = mgag200_crtc_state->format; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_rect fullscreen = { .x1 = 0, @@ -706,7 +705,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, if (mdev->type == G200_WB || mdev->type == G200_EW3) mgag200_g200wb_hold_bmc(mdev); - mgag200_set_format_regs(mdev, fb); + mgag200_set_format_regs(mdev, format); mgag200_set_mode_regs(mdev, adjusted_mode); pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc); @@ -715,7 +714,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, mgag200_g200er_reset_tagfifo(mdev); if (IS_G200_SE(mdev)) - mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, fb); + mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format); else if (mdev->type == G200_EV) mgag200_g200ev_set_hiprilvl(mdev); @@ -723,9 +722,9 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, mgag200_g200wb_release_bmc(mdev); if (crtc_state->gamma_lut) - mgag200_crtc_set_gamma(mdev, fb->format, crtc_state->gamma_lut->data); + mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data); else - mgag200_crtc_set_gamma_linear(mdev, fb->format); + mgag200_crtc_set_gamma_linear(mdev, format); mgag200_enable_display(mdev); @@ -768,6 +767,8 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe, if (!fb || (fb->format != new_fb->format)) crtc_state->mode_changed = true; /* update PLL settings */ + mgag200_crtc_state->format = new_fb->format; + if (crtc_state->mode_changed) { ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock, &mgag200_crtc_state->pixpllc); @@ -831,6 +832,7 @@ mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe return NULL; __drm_atomic_helper_crtc_duplicate_state(crtc, &new_mgag200_crtc_state->base); + new_mgag200_crtc_state->format = mgag200_crtc_state->format; memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc, sizeof(new_mgag200_crtc_state->pixpllc)); From 4f4dc37e374c957b2bbcd3b1f3dad73afeb647a5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:55 +0200 Subject: [PATCH 228/396] drm/mgag200: Reorganize before dropping simple-KMS helpers Move around some modesetting code before dropping simple-KMS helpers. Makes the next patch more readable. No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-7-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_mode.c | 95 +++++++++++++------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index e392e2646359..3767491b07d7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -603,42 +603,31 @@ static void mgag200_disable_display(struct mga_device *mdev) WREG_ECRT(0x01, crtcext1); } -/* - * Connector - */ - -static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector) +static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_map *vmap, + struct drm_framebuffer *fb, const struct drm_rect *clip) { - struct mga_device *mdev = to_mga_device(connector->dev); - int ret; + void __iomem *dst = mdev->vram; + void *vaddr = vmap[0].vaddr; /* TODO: Use mapping abstraction properly */ - /* - * Protect access to I/O registers from concurrent modesetting - * by acquiring the I/O-register lock. - */ - mutex_lock(&mdev->rmmio_lock); - ret = drm_connector_helper_get_modes_from_ddc(connector); - mutex_unlock(&mdev->rmmio_lock); - - return ret; + dst += drm_fb_clip_offset(fb->pitches[0], fb->format, clip); + drm_fb_memcpy_toio(dst, fb->pitches[0], vaddr, fb, clip); } -static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = { - .get_modes = mgag200_vga_connector_helper_get_modes, -}; - -static const struct drm_connector_funcs mga_vga_connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - /* * Simple Display Pipe */ +static const uint32_t mgag200_simple_display_pipe_formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, +}; + +static const uint64_t mgag200_simple_display_pipe_fmtmods[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + static enum drm_mode_status mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, const struct drm_display_mode *mode) @@ -670,17 +659,6 @@ mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, return MODE_OK; } -static void -mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb, - struct drm_rect *clip, const struct iosys_map *map) -{ - void __iomem *dst = mdev->vram; - void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ - - dst += drm_fb_clip_offset(fb->pitches[0], fb->format, clip); - drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, clip); -} - static void mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, @@ -728,7 +706,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, mgag200_enable_display(mdev); - mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]); + mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &fullscreen); /* Always scanout image at VRAM offset 0 */ mgag200_set_startadd(mdev, (u32)0); @@ -809,7 +787,7 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, drm_atomic_helper_damage_iter_init(&iter, old_state, state); drm_atomic_for_each_plane_damage(&iter, &damage) { - mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]); + mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage); } /* Always scanout image at VRAM offset 0 */ mgag200_set_startadd(mdev, (u32)0); @@ -877,15 +855,36 @@ mgag200_simple_display_pipe_funcs = { DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, }; -static const uint32_t mgag200_simple_display_pipe_formats[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB565, - DRM_FORMAT_RGB888, +/* + * Connector + */ + +static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector) +{ + struct mga_device *mdev = to_mga_device(connector->dev); + int ret; + + /* + * Protect access to I/O registers from concurrent modesetting + * by acquiring the I/O-register lock. + */ + mutex_lock(&mdev->rmmio_lock); + ret = drm_connector_helper_get_modes_from_ddc(connector); + mutex_unlock(&mdev->rmmio_lock); + + return ret; +} + +static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = { + .get_modes = mgag200_vga_connector_helper_get_modes, }; -static const uint64_t mgag200_simple_display_pipe_fmtmods[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID +static const struct drm_connector_funcs mga_vga_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; /* From 1baf9127c482a3a58aef81d92ae751798e2db202 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:56 +0200 Subject: [PATCH 229/396] drm/mgag200: Replace simple-KMS with regular atomic helpers Drop simple-KMS in favor of regular atomic helpers. Makes the code more modular and hence better to adapt to per-model requirements. The simple-KMS helpers provide few extra features, so the patch is mostly about open-coding what simple-KMS does. The simple-KMS helpers do mix up plane and CRTC state. Changing to regular atomic helpers requires to split some of the simple-pipe functions into per-plane and per-CRTC code No functional changes. v3: * always run drm_atomic_helper_check_plane_state() * clean up style Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-8-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.h | 8 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 384 +++++++++++++++---------- 2 files changed, 234 insertions(+), 158 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index bf6a01ff9719..b0433985ec0d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -15,11 +15,13 @@ #include <video/vga.h> +#include <drm/drm_connector.h> +#include <drm/drm_crtc.h> #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> #include <drm/drm_gem_shmem_helper.h> -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_plane.h> #include "mgag200_reg.h" @@ -276,9 +278,11 @@ struct mga_device { enum mga_type type; struct mgag200_pll pixpll; + struct drm_plane primary_plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct mga_i2c_chan i2c; struct drm_connector connector; - struct drm_simple_display_pipe display_pipe; }; static inline struct mga_device *to_mga_device(struct drm_device *dev) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 3767491b07d7..461da1409fdf 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -23,7 +23,6 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #include "mgag200_drv.h" @@ -614,25 +613,106 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma } /* - * Simple Display Pipe + * Primary plane */ -static const uint32_t mgag200_simple_display_pipe_formats[] = { +static const uint32_t mgag200_primary_plane_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_RGB888, }; -static const uint64_t mgag200_simple_display_pipe_fmtmods[] = { +static const uint64_t mgag200_primary_plane_fmtmods[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID }; -static enum drm_mode_status -mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +static int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *new_state) { - struct mga_device *mdev = to_mga_device(pipe->crtc.dev); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); + struct drm_framebuffer *new_fb = new_plane_state->fb; + struct drm_framebuffer *fb = NULL; + struct drm_crtc *new_crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = NULL; + struct mgag200_crtc_state *new_mgag200_crtc_state; + int ret; + + if (new_crtc) + new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc); + + ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, true); + if (ret) + return ret; + else if (!new_plane_state->visible) + return 0; + + if (plane->state) + fb = plane->state->fb; + + if (!fb || (fb->format != new_fb->format)) + new_crtc_state->mode_changed = true; /* update PLL settings */ + + new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + new_mgag200_crtc_state->format = new_fb->format; + + return 0; +} + +static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = plane->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_plane_state *plane_state = plane->state; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane); + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + struct drm_framebuffer *fb = plane_state->fb; + struct drm_atomic_helper_damage_iter iter; + struct drm_rect damage; + + if (!fb) + return; + + drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); + drm_atomic_for_each_plane_damage(&iter, &damage) { + mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage); + } + + /* Always scanout image at VRAM offset 0 */ + mgag200_set_startadd(mdev, (u32)0); + mgag200_set_offset(mdev, fb); +} + +static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *old_state) +{ } + +static const struct drm_plane_helper_funcs mgag200_primary_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = mgag200_primary_plane_helper_atomic_check, + .atomic_update = mgag200_primary_plane_helper_atomic_update, + .atomic_disable = mgag200_primary_plane_helper_atomic_disable, +}; + +static const struct drm_plane_funcs mgag200_primary_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +/* + * CRTC + */ + +static enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) +{ + struct mga_device *mdev = to_mga_device(crtc->dev); const struct mgag200_device_info *info = mdev->info; /* @@ -659,26 +739,69 @@ mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, return MODE_OK; } -static void -mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *dev = crtc->dev; struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); struct mgag200_pll *pixpll = &mdev->pixpll; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut; + int ret; + + ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false); + if (ret) + return ret; + + if (!new_crtc_state->enable) + return 0; + + if (new_crtc_state->mode_changed) { + ret = pixpll->funcs->compute(pixpll, new_crtc_state->mode.clock, + &mgag200_crtc_state->pixpllc); + if (ret) + return ret; + } + + if (new_crtc_state->color_mgmt_changed && new_gamma_lut) { + if (new_gamma_lut->length != MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) { + drm_dbg(dev, "Wrong size for gamma_lut %zu\n", new_gamma_lut->length); + return -EINVAL; + } + } + + return drm_atomic_add_affected_planes(new_state, crtc); +} + +static void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + + if (crtc_state->enable && crtc_state->color_mgmt_changed) { + const struct drm_format_info *format = mgag200_crtc_state->format; + + if (crtc_state->gamma_lut) + mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data); + else + mgag200_crtc_set_gamma_linear(mdev, format); + } +} + +static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); - struct drm_framebuffer *fb = plane_state->fb; const struct drm_format_info *format = mgag200_crtc_state->format; - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - struct drm_rect fullscreen = { - .x1 = 0, - .x2 = fb->width, - .y1 = 0, - .y2 = fb->height, - }; + struct mgag200_pll *pixpll = &mdev->pixpll; if (mdev->type == G200_WB || mdev->type == G200_EW3) mgag200_g200wb_hold_bmc(mdev); @@ -696,108 +819,50 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, else if (mdev->type == G200_EV) mgag200_g200ev_set_hiprilvl(mdev); - if (mdev->type == G200_WB || mdev->type == G200_EW3) - mgag200_g200wb_release_bmc(mdev); - - if (crtc_state->gamma_lut) - mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data); - else - mgag200_crtc_set_gamma_linear(mdev, format); - mgag200_enable_display(mdev); - mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &fullscreen); - - /* Always scanout image at VRAM offset 0 */ - mgag200_set_startadd(mdev, (u32)0); - mgag200_set_offset(mdev, fb); + if (mdev->type == G200_WB || mdev->type == G200_EW3) + mgag200_g200wb_release_bmc(mdev); } -static void -mgag200_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) +static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) { - struct drm_crtc *crtc = &pipe->crtc; struct mga_device *mdev = to_mga_device(crtc->dev); + if (mdev->type == G200_WB || mdev->type == G200_EW3) + mgag200_g200wb_hold_bmc(mdev); + mgag200_disable_display(mdev); + + if (mdev->type == G200_WB || mdev->type == G200_EW3) + mgag200_g200wb_release_bmc(mdev); } -static int -mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state) +static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = { + .mode_valid = mgag200_crtc_helper_mode_valid, + .atomic_check = mgag200_crtc_helper_atomic_check, + .atomic_flush = mgag200_crtc_helper_atomic_flush, + .atomic_enable = mgag200_crtc_helper_atomic_enable, + .atomic_disable = mgag200_crtc_helper_atomic_disable, +}; + +static void mgag200_crtc_reset(struct drm_crtc *crtc) { - struct drm_plane *plane = plane_state->plane; - struct drm_device *dev = plane->dev; - struct mga_device *mdev = to_mga_device(dev); - struct mgag200_pll *pixpll = &mdev->pixpll; - struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); - struct drm_framebuffer *new_fb = plane_state->fb; - struct drm_framebuffer *fb = NULL; - int ret; + struct mgag200_crtc_state *mgag200_crtc_state; - if (!new_fb) - return 0; + if (crtc->state) + crtc->funcs->atomic_destroy_state(crtc, crtc->state); - if (plane->state) - fb = plane->state->fb; - - if (!fb || (fb->format != new_fb->format)) - crtc_state->mode_changed = true; /* update PLL settings */ - - mgag200_crtc_state->format = new_fb->format; - - if (crtc_state->mode_changed) { - ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock, - &mgag200_crtc_state->pixpllc); - if (ret) - return ret; - } - - if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) { - if (crtc_state->gamma_lut->length != - MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) { - drm_err(dev, "Wrong size for gamma_lut %zu\n", - crtc_state->gamma_lut->length); - return -EINVAL; - } - } - return 0; + mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL); + if (mgag200_crtc_state) + __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base); + else + __drm_atomic_helper_crtc_reset(crtc, NULL); } -static void -mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) +static struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { - struct drm_plane *plane = &pipe->plane; - struct drm_crtc *crtc = &pipe->crtc; - struct drm_device *dev = plane->dev; - struct mga_device *mdev = to_mga_device(dev); - struct drm_plane_state *state = plane->state; - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); - struct drm_framebuffer *fb = state->fb; - struct drm_rect damage; - struct drm_atomic_helper_damage_iter iter; - - if (!fb) - return; - - if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut) - mgag200_crtc_set_gamma(mdev, fb->format, crtc->state->gamma_lut->data); - - drm_atomic_helper_damage_iter_init(&iter, old_state, state); - drm_atomic_for_each_plane_damage(&iter, &damage) { - mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage); - } - /* Always scanout image at VRAM offset 0 */ - mgag200_set_startadd(mdev, (u32)0); - mgag200_set_offset(mdev, fb); -} - -static struct drm_crtc_state * -mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe *pipe) -{ - struct drm_crtc *crtc = &pipe->crtc; struct drm_crtc_state *crtc_state = crtc->state; struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); struct mgag200_crtc_state *new_mgag200_crtc_state; @@ -817,8 +882,8 @@ mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe return &new_mgag200_crtc_state->base; } -static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state) +static void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) { struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); @@ -826,33 +891,21 @@ static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_dis kfree(mgag200_crtc_state); } -static void mgag200_simple_display_pipe_reset_crtc(struct drm_simple_display_pipe *pipe) -{ - struct drm_crtc *crtc = &pipe->crtc; - struct mgag200_crtc_state *mgag200_crtc_state; +static const struct drm_crtc_funcs mgag200_crtc_funcs = { + .reset = mgag200_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, + .atomic_destroy_state = mgag200_crtc_atomic_destroy_state, +}; - if (crtc->state) { - mgag200_simple_display_pipe_destroy_crtc_state(pipe, crtc->state); - crtc->state = NULL; /* must be set to NULL here */ - } +/* + * Encoder + */ - mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL); - if (!mgag200_crtc_state) - return; - __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base); -} - -static const struct drm_simple_display_pipe_funcs -mgag200_simple_display_pipe_funcs = { - .mode_valid = mgag200_simple_display_pipe_mode_valid, - .enable = mgag200_simple_display_pipe_enable, - .disable = mgag200_simple_display_pipe_disable, - .check = mgag200_simple_display_pipe_check, - .update = mgag200_simple_display_pipe_update, - .reset_crtc = mgag200_simple_display_pipe_reset_crtc, - .duplicate_crtc_state = mgag200_simple_display_pipe_duplicate_crtc_state, - .destroy_crtc_state = mgag200_simple_display_pipe_destroy_crtc_state, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, +static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; /* @@ -998,12 +1051,49 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra static int mgag200_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; struct mga_i2c_chan *i2c = &mdev->i2c; struct drm_connector *connector = &mdev->connector; - struct drm_simple_display_pipe *pipe = &mdev->display_pipe; - size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats); int ret; + ret = mgag200_pixpll_init(&mdev->pixpll, mdev); + if (ret) + return ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_primary_plane_funcs, + mgag200_primary_plane_formats, + ARRAY_SIZE(mgag200_primary_plane_formats), + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, &mgag200_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + ret = mgag200_i2c_init(mdev, i2c); if (ret) { drm_err(dev, "failed to add DDC bus: %d\n", ret); @@ -1020,30 +1110,12 @@ static int mgag200_pipeline_init(struct mga_device *mdev) } drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs); - ret = mgag200_pixpll_init(&mdev->pixpll, mdev); - if (ret) - return ret; - - ret = drm_simple_display_pipe_init(dev, pipe, - &mgag200_simple_display_pipe_funcs, - mgag200_simple_display_pipe_formats, - format_count, - mgag200_simple_display_pipe_fmtmods, - connector); + ret = drm_connector_attach_encoder(connector, encoder); if (ret) { - drm_err(dev, - "drm_simple_display_pipe_init() failed, error %d\n", - ret); + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); return ret; } - drm_plane_enable_fb_damage_clips(&pipe->plane); - - /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ - drm_mode_crtc_set_gamma_size(&pipe->crtc, MGAG200_LUT_SIZE); - - drm_crtc_enable_color_mgmt(&pipe->crtc, 0, false, MGAG200_LUT_SIZE); - return 0; } From 5cd062e31d352e33284d08a52ddb2b9ed1a5caa8 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:57 +0200 Subject: [PATCH 230/396] drm/mgag200: Set SCROFF in primary-plane code The SCROFF bit controls reading the primary plane's scanout buffer from video memory. Set it from primary-plane code, instead of CRTC code. v3: * only flip SCROFF when enabling/disabling the plane (Jocelyn) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-9-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_mode.c | 35 +++++++++++++++----------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 461da1409fdf..7536a9a41bd6 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -549,7 +549,7 @@ static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev) static void mgag200_enable_display(struct mga_device *mdev) { - u8 seq0, seq1, crtcext1; + u8 seq0, crtcext1; RREG_SEQ(0x00, seq0); seq0 |= MGAREG_SEQ0_SYNCRST | @@ -563,12 +563,6 @@ static void mgag200_enable_display(struct mga_device *mdev) mga_wait_vsync(mdev); mga_wait_busy(mdev); - RREG_SEQ(0x01, seq1); - seq1 &= ~MGAREG_SEQ1_SCROFF; - WREG_SEQ(0x01, seq1); - - msleep(20); - RREG_ECRT(0x01, crtcext1); crtcext1 &= ~MGAREG_CRTCEXT1_VSYNCOFF; crtcext1 &= ~MGAREG_CRTCEXT1_HSYNCOFF; @@ -577,7 +571,7 @@ static void mgag200_enable_display(struct mga_device *mdev) static void mgag200_disable_display(struct mga_device *mdev) { - u8 seq0, seq1, crtcext1; + u8 seq0, crtcext1; RREG_SEQ(0x00, seq0); seq0 &= ~MGAREG_SEQ0_SYNCRST; @@ -590,12 +584,6 @@ static void mgag200_disable_display(struct mga_device *mdev) mga_wait_vsync(mdev); mga_wait_busy(mdev); - RREG_SEQ(0x01, seq1); - seq1 |= MGAREG_SEQ1_SCROFF; - WREG_SEQ(0x01, seq1); - - msleep(20); - RREG_ECRT(0x01, crtcext1); crtcext1 |= MGAREG_CRTCEXT1_VSYNCOFF | MGAREG_CRTCEXT1_HSYNCOFF; @@ -673,6 +661,7 @@ static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, struct drm_framebuffer *fb = plane_state->fb; struct drm_atomic_helper_damage_iter iter; struct drm_rect damage; + u8 seq1; if (!fb) return; @@ -685,11 +674,27 @@ static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, /* Always scanout image at VRAM offset 0 */ mgag200_set_startadd(mdev, (u32)0); mgag200_set_offset(mdev, fb); + + if (!old_plane_state->crtc && plane_state->crtc) { // enabling + RREG_SEQ(0x01, seq1); + seq1 &= ~MGAREG_SEQ1_SCROFF; + WREG_SEQ(0x01, seq1); + msleep(20); + } } static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *old_state) -{ } +{ + struct drm_device *dev = plane->dev; + struct mga_device *mdev = to_mga_device(dev); + u8 seq1; + + RREG_SEQ(0x01, seq1); + seq1 |= MGAREG_SEQ1_SCROFF; + WREG_SEQ(0x01, seq1); + msleep(20); +} static const struct drm_plane_helper_funcs mgag200_primary_plane_helper_funcs = { DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, From f639f74a789570fff9fb093a603bda550b53f3d9 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:58 +0200 Subject: [PATCH 231/396] drm/mgag200: Add per-device callbacks While currently empty, the device callbacks will allow mgag200's modesetting code to interact with the BMC and PIXPLLC. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-10-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 4 +++- drivers/gpu/drm/mgag200/mgag200_drv.h | 7 ++++++- drivers/gpu/drm/mgag200/mgag200_g200.c | 6 +++++- drivers/gpu/drm/mgag200/mgag200_g200eh.c | 6 +++++- drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 6 +++++- drivers/gpu/drm/mgag200/mgag200_g200er.c | 6 +++++- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 6 +++++- drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 6 +++++- drivers/gpu/drm/mgag200/mgag200_g200se.c | 5 ++++- drivers/gpu/drm/mgag200/mgag200_g200wb.c | 6 +++++- 10 files changed, 48 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 73e8e4e9e54b..c20a59a2cd91 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -162,13 +162,15 @@ int mgag200_device_preinit(struct mga_device *mdev) } int mgag200_device_init(struct mga_device *mdev, enum mga_type type, - const struct mgag200_device_info *info) + const struct mgag200_device_info *info, + const struct mgag200_device_funcs *funcs) { struct drm_device *dev = &mdev->base; u8 crtcext3, misc; int ret; mdev->info = info; + mdev->funcs = funcs; mdev->type = type; ret = drmm_mutex_init(dev, &mdev->rmmio_lock); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index b0433985ec0d..db29eef8981b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -262,10 +262,14 @@ struct mgag200_device_info { .bug_no_startadd = (_bug_no_startadd), \ } +struct mgag200_device_funcs { +}; + struct mga_device { struct drm_device base; const struct mgag200_device_info *info; + const struct mgag200_device_funcs *funcs; struct resource *rmmio_res; void __iomem *rmmio; @@ -322,7 +326,8 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size); resource_size_t mgag200_device_probe_vram(struct mga_device *mdev); int mgag200_device_preinit(struct mga_device *mdev); int mgag200_device_init(struct mga_device *mdev, enum mga_type type, - const struct mgag200_device_info *info); + const struct mgag200_device_info *info, + const struct mgag200_device_funcs *funcs); /* mgag200_<device type>.c */ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv, diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c index 4a5af20efa36..e11b485d470d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c @@ -183,6 +183,9 @@ out: pci_unmap_rom(pdev, rom); } +static const struct mgag200_device_funcs mgag200_g200_device_funcs = { +}; + struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type) { @@ -210,7 +213,8 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct mgag200_g200_init_refclk(g200); - ret = mgag200_device_init(mdev, type, &mgag200_g200_device_info); + ret = mgag200_device_init(mdev, type, &mgag200_g200_device_info, + &mgag200_g200_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c index f2c53fe8d927..473ff5217db5 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c @@ -37,6 +37,9 @@ void mgag200_g200eh_init_registers(struct mga_device *mdev) static const struct mgag200_device_info mgag200_g200eh_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false, 1, 0, false); +static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = { +}; + struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type) { @@ -60,7 +63,8 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200eh_device_info); + ret = mgag200_device_init(mdev, type, &mgag200_g200eh_device_info, + &mgag200_g200eh_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c index adb9190b62af..99e00aa848e1 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c @@ -13,6 +13,9 @@ static const struct mgag200_device_info mgag200_g200eh3_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false, 1, 0, false); +static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = { +}; + struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type) @@ -37,7 +40,8 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200eh3_device_info); + ret = mgag200_device_init(mdev, type, &mgag200_g200eh3_device_info, + &mgag200_g200eh3_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 8ff050906e1c..1c9a963dd9c5 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -38,6 +38,9 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev) static const struct mgag200_device_info mgag200_g200er_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 1, 0, false); +static const struct mgag200_device_funcs mgag200_g200er_device_funcs = { +}; + struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type) { @@ -57,7 +60,8 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200er_device_info); + ret = mgag200_device_init(mdev, type, &mgag200_g200er_device_info, + &mgag200_g200er_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index 0dc5c342e7c4..a0dc72a69f52 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -38,6 +38,9 @@ static void mgag200_g200ev_init_registers(struct mga_device *mdev) static const struct mgag200_device_info mgag200_g200ev_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false, 0, 1, false); +static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = { +}; + struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type) { @@ -61,7 +64,8 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200ev_device_info); + ret = mgag200_device_init(mdev, type, &mgag200_g200ev_device_info, + &mgag200_g200ev_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index a4ecdd3784a3..202db00bb62e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -20,6 +20,9 @@ static void mgag200_g200ew3_init_registers(struct mga_device *mdev) static const struct mgag200_device_info mgag200_g200ew3_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false); +static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = { +}; + static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev) { resource_size_t vram_size = resource_size(mdev->vram_res); @@ -53,7 +56,8 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200ew3_device_info); + ret = mgag200_device_init(mdev, type, &mgag200_g200ew3_device_info, + &mgag200_g200ew3_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index bd8fc7a177c2..7a7648d7de93 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -93,6 +93,9 @@ static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200s return 0; } +static const struct mgag200_device_funcs mgag200_g200se_device_funcs = { +}; + struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type) { @@ -144,7 +147,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru return ERR_PTR(-EINVAL); } - ret = mgag200_device_init(mdev, type, info); + ret = mgag200_device_init(mdev, type, info, &mgag200_g200se_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index 05f17986b95a..2b5dd0cc38e2 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -35,6 +35,9 @@ void mgag200_g200wb_init_registers(struct mga_device *mdev) static const struct mgag200_device_info mgag200_g200wb_device_info = MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false); +static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = { +}; + struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type) { @@ -58,7 +61,8 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200wb_device_info); + ret = mgag200_device_init(mdev, type, &mgag200_g200wb_device_info, + &mgag200_g200wb_device_funcs); if (ret) return ERR_PTR(ret); From 8aeeb3144fe27b2b8aa30db262de2f654f2edb9a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:40:59 +0200 Subject: [PATCH 232/396] drm/mgag200: Provide per-device callbacks for BMC synchronization Move the BMC-related code into its own file and wire it up with device callbacks. While programming a new display mode, G200EW3 and G200WB have to de- synchronize with the BMC. Synchronization is done via VIDRST pins and controlled via VRSTEN and HRSTEN bits. Move the BMC code behind a serviceable interface and call it from the CRTC's enable and disable functions. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-11-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/Makefile | 1 + drivers/gpu/drm/mgag200/mgag200_bmc.c | 99 ++++++++++++++++++++ drivers/gpu/drm/mgag200/mgag200_drv.h | 15 +++ drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 2 + drivers/gpu/drm/mgag200/mgag200_g200wb.c | 2 + drivers/gpu/drm/mgag200/mgag200_mode.c | 107 ++-------------------- 6 files changed, 129 insertions(+), 97 deletions(-) create mode 100644 drivers/gpu/drm/mgag200/mgag200_bmc.c diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile index 89558549c3af..94d465a2b753 100644 --- a/drivers/gpu/drm/mgag200/Makefile +++ b/drivers/gpu/drm/mgag200/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only mgag200-y := \ + mgag200_bmc.o \ mgag200_drv.o \ mgag200_g200.o \ mgag200_g200eh.o \ diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c new file mode 100644 index 000000000000..2ba2e3c5086a --- /dev/null +++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/delay.h> + +#include "mgag200_drv.h" + +void mgag200_bmc_disable_vidrst(struct mga_device *mdev) +{ + u8 tmp; + int iter_max; + + /* + * 1 - The first step is to inform the BMC of an upcoming mode + * change. We are putting the misc<0> to output. + */ + + WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL); + tmp = RREG8(DAC_DATA); + tmp |= 0x10; + WREG_DAC(MGA1064_GEN_IO_CTL, tmp); + + /* we are putting a 1 on the misc<0> line */ + WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA); + tmp = RREG8(DAC_DATA); + tmp |= 0x10; + WREG_DAC(MGA1064_GEN_IO_DATA, tmp); + + /* + * 2- Second step to mask any further scan request. This is + * done by asserting the remfreqmsk bit (XSPAREREG<7>) + */ + + WREG8(DAC_INDEX, MGA1064_SPAREREG); + tmp = RREG8(DAC_DATA); + tmp |= 0x80; + WREG_DAC(MGA1064_SPAREREG, tmp); + + /* + * 3a- The third step is to verify if there is an active scan. + * We are waiting for a 0 on remhsyncsts <XSPAREREG<0>). + */ + iter_max = 300; + while (!(tmp & 0x1) && iter_max) { + WREG8(DAC_INDEX, MGA1064_SPAREREG); + tmp = RREG8(DAC_DATA); + udelay(1000); + iter_max--; + } + + /* + * 3b- This step occurs only if the remove is actually + * scanning. We are waiting for the end of the frame which is + * a 1 on remvsyncsts (XSPAREREG<1>) + */ + if (iter_max) { + iter_max = 300; + while ((tmp & 0x2) && iter_max) { + WREG8(DAC_INDEX, MGA1064_SPAREREG); + tmp = RREG8(DAC_DATA); + udelay(1000); + iter_max--; + } + } +} + +void mgag200_bmc_enable_vidrst(struct mga_device *mdev) +{ + u8 tmp; + + /* Ensure that the vrsten and hrsten are set */ + WREG8(MGAREG_CRTCEXT_INDEX, 1); + tmp = RREG8(MGAREG_CRTCEXT_DATA); + WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88); + + /* Assert rstlvl2 */ + WREG8(DAC_INDEX, MGA1064_REMHEADCTL2); + tmp = RREG8(DAC_DATA); + tmp |= 0x8; + WREG8(DAC_DATA, tmp); + + udelay(10); + + /* Deassert rstlvl2 */ + tmp &= ~0x08; + WREG8(DAC_INDEX, MGA1064_REMHEADCTL2); + WREG8(DAC_DATA, tmp); + + /* Remove mask of scan request */ + WREG8(DAC_INDEX, MGA1064_SPAREREG); + tmp = RREG8(DAC_DATA); + tmp &= ~0x80; + WREG8(DAC_DATA, tmp); + + /* Put back a 0 on the misc<0> line */ + WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA); + tmp = RREG8(DAC_DATA); + tmp &= ~0x10; + WREG_DAC(MGA1064_GEN_IO_DATA, tmp); +} diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index db29eef8981b..e78c1b2f5c27 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -263,6 +263,17 @@ struct mgag200_device_info { } struct mgag200_device_funcs { + /* + * Disables an external reset source (i.e., BMC) before programming + * a new display mode. + */ + void (*disable_vidrst)(struct mga_device *mdev); + + /* + * Enables an external reset source (i.e., BMC) after programming + * a new display mode. + */ + void (*enable_vidrst)(struct mga_device *mdev); }; struct mga_device { @@ -354,6 +365,10 @@ resource_size_t mgag200_device_probe_vram(struct mga_device *mdev); void mgag200_init_registers(struct mga_device *mdev); int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available); + /* mgag200_bmc.c */ +void mgag200_bmc_disable_vidrst(struct mga_device *mdev); +void mgag200_bmc_enable_vidrst(struct mga_device *mdev); + /* mgag200_i2c.c */ int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index 202db00bb62e..19a870120ebc 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -21,6 +21,8 @@ static const struct mgag200_device_info mgag200_g200ew3_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false); static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = { + .disable_vidrst = mgag200_bmc_disable_vidrst, + .enable_vidrst = mgag200_bmc_enable_vidrst, }; static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev) diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index 2b5dd0cc38e2..91d2848b4b06 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -36,6 +36,8 @@ static const struct mgag200_device_info mgag200_g200wb_device_info = MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false); static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = { + .disable_vidrst = mgag200_bmc_disable_vidrst, + .enable_vidrst = mgag200_bmc_enable_vidrst, }; struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 7536a9a41bd6..2b1e9f069366 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -131,95 +131,6 @@ static inline void mga_wait_busy(struct mga_device *mdev) } while ((status & 0x01) && time_before(jiffies, timeout)); } -static void mgag200_g200wb_hold_bmc(struct mga_device *mdev) -{ - u8 tmp; - int iter_max; - - /* 1- The first step is to warn the BMC of an upcoming mode change. - * We are putting the misc<0> to output.*/ - - WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL); - tmp = RREG8(DAC_DATA); - tmp |= 0x10; - WREG_DAC(MGA1064_GEN_IO_CTL, tmp); - - /* we are putting a 1 on the misc<0> line */ - WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA); - tmp = RREG8(DAC_DATA); - tmp |= 0x10; - WREG_DAC(MGA1064_GEN_IO_DATA, tmp); - - /* 2- Second step to mask and further scan request - * This will be done by asserting the remfreqmsk bit (XSPAREREG<7>) - */ - WREG8(DAC_INDEX, MGA1064_SPAREREG); - tmp = RREG8(DAC_DATA); - tmp |= 0x80; - WREG_DAC(MGA1064_SPAREREG, tmp); - - /* 3a- the third step is to verifu if there is an active scan - * We are searching for a 0 on remhsyncsts <XSPAREREG<0>) - */ - iter_max = 300; - while (!(tmp & 0x1) && iter_max) { - WREG8(DAC_INDEX, MGA1064_SPAREREG); - tmp = RREG8(DAC_DATA); - udelay(1000); - iter_max--; - } - - /* 3b- this step occurs only if the remove is actually scanning - * we are waiting for the end of the frame which is a 1 on - * remvsyncsts (XSPAREREG<1>) - */ - if (iter_max) { - iter_max = 300; - while ((tmp & 0x2) && iter_max) { - WREG8(DAC_INDEX, MGA1064_SPAREREG); - tmp = RREG8(DAC_DATA); - udelay(1000); - iter_max--; - } - } -} - -static void mgag200_g200wb_release_bmc(struct mga_device *mdev) -{ - u8 tmp; - - /* 1- The first step is to ensure that the vrsten and hrsten are set */ - WREG8(MGAREG_CRTCEXT_INDEX, 1); - tmp = RREG8(MGAREG_CRTCEXT_DATA); - WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88); - - /* 2- second step is to assert the rstlvl2 */ - WREG8(DAC_INDEX, MGA1064_REMHEADCTL2); - tmp = RREG8(DAC_DATA); - tmp |= 0x8; - WREG8(DAC_DATA, tmp); - - /* wait 10 us */ - udelay(10); - - /* 3- deassert rstlvl2 */ - tmp &= ~0x08; - WREG8(DAC_INDEX, MGA1064_REMHEADCTL2); - WREG8(DAC_DATA, tmp); - - /* 4- remove mask of scan request */ - WREG8(DAC_INDEX, MGA1064_SPAREREG); - tmp = RREG8(DAC_DATA); - tmp &= ~0x80; - WREG8(DAC_DATA, tmp); - - /* 5- put back a 0 on the misc<0> line */ - WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA); - tmp = RREG8(DAC_DATA); - tmp &= ~0x10; - WREG_DAC(MGA1064_GEN_IO_DATA, tmp); -} - /* * This is how the framebuffer base address is stored in g200 cards: * * Assume @offset is the gpu_addr variable of the framebuffer object @@ -802,14 +713,15 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct mga_device *mdev = to_mga_device(dev); + const struct mgag200_device_funcs *funcs = mdev->funcs; struct drm_crtc_state *crtc_state = crtc->state; struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); const struct drm_format_info *format = mgag200_crtc_state->format; struct mgag200_pll *pixpll = &mdev->pixpll; - if (mdev->type == G200_WB || mdev->type == G200_EW3) - mgag200_g200wb_hold_bmc(mdev); + if (funcs->disable_vidrst) + funcs->disable_vidrst(mdev); mgag200_set_format_regs(mdev, format); mgag200_set_mode_regs(mdev, adjusted_mode); @@ -826,22 +738,23 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_enable_display(mdev); - if (mdev->type == G200_WB || mdev->type == G200_EW3) - mgag200_g200wb_release_bmc(mdev); + if (funcs->enable_vidrst) + funcs->enable_vidrst(mdev); } static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state) { struct mga_device *mdev = to_mga_device(crtc->dev); + const struct mgag200_device_funcs *funcs = mdev->funcs; - if (mdev->type == G200_WB || mdev->type == G200_EW3) - mgag200_g200wb_hold_bmc(mdev); + if (funcs->disable_vidrst) + funcs->disable_vidrst(mdev); mgag200_disable_display(mdev); - if (mdev->type == G200_WB || mdev->type == G200_EW3) - mgag200_g200wb_release_bmc(mdev); + if (funcs->enable_vidrst) + funcs->enable_vidrst(mdev); } static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = { From 877507bb954e7d0a4f2d3ba9957127a83c03e447 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:41:00 +0200 Subject: [PATCH 233/396] drm/mgag200: Provide per-device callbacks for PIXPLLC Move the PIXPLLC code into per-model source files and wire it up with per-model callbacks. No functional changes. The PIXPLLC pixel-clock is part of the CRTC, but really separate hardware that varies with each model of the G200. Move the PIXPLLC code for each model into the per-model source file and call it from CRTC helpers via device functions. This allows to remove struct mgag200_pll and the related code. The new callbacks behave like the CRTC's atomic_check and atomic_enable functions. v3: * clean up style Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-12-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/Makefile | 3 +- drivers/gpu/drm/mgag200/mgag200_drv.h | 32 +- drivers/gpu/drm/mgag200/mgag200_g200.c | 109 +++ drivers/gpu/drm/mgag200/mgag200_g200eh.c | 131 +++ drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 59 ++ drivers/gpu/drm/mgag200/mgag200_g200er.c | 120 +++ drivers/gpu/drm/mgag200/mgag200_g200ev.c | 132 +++ drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 61 ++ drivers/gpu/drm/mgag200/mgag200_g200se.c | 211 ++++- drivers/gpu/drm/mgag200/mgag200_g200wb.c | 180 ++++ drivers/gpu/drm/mgag200/mgag200_mode.c | 20 +- drivers/gpu/drm/mgag200/mgag200_pll.c | 997 ---------------------- 12 files changed, 1026 insertions(+), 1029 deletions(-) delete mode 100644 drivers/gpu/drm/mgag200/mgag200_pll.c diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile index 94d465a2b753..182e224c460d 100644 --- a/drivers/gpu/drm/mgag200/Makefile +++ b/drivers/gpu/drm/mgag200/Makefile @@ -11,7 +11,6 @@ mgag200-y := \ mgag200_g200se.o \ mgag200_g200wb.o \ mgag200_i2c.o \ - mgag200_mode.o \ - mgag200_pll.o + mgag200_mode.o obj-$(CONFIG_DRM_MGAG200) += mgag200.o diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index e78c1b2f5c27..cc14028df395 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -156,7 +156,6 @@ #define MGAG200_MAX_FB_WIDTH 4096 struct mga_device; -struct mgag200_pll; /* * Stores parameters for programming the PLLs @@ -175,17 +174,6 @@ struct mgag200_pll_values { unsigned int s; }; -struct mgag200_pll_funcs { - int (*compute)(struct mgag200_pll *pll, long clock, struct mgag200_pll_values *pllc); - void (*update)(struct mgag200_pll *pll, const struct mgag200_pll_values *pllc); -}; - -struct mgag200_pll { - struct mga_device *mdev; - - const struct mgag200_pll_funcs *funcs; -}; - struct mgag200_crtc_state { struct drm_crtc_state base; @@ -274,6 +262,20 @@ struct mgag200_device_funcs { * a new display mode. */ void (*enable_vidrst)(struct mga_device *mdev); + + /* + * Validate that the given state can be programmed into PIXPLLC. On + * success, the calculated parameters should be stored in the CRTC's + * state in struct @mgag200_crtc_state.pixpllc. + */ + int (*pixpllc_atomic_check)(struct drm_crtc *crtc, struct drm_atomic_state *new_state); + + /* + * Program PIXPLLC from the CRTC state. The parameters should have been + * stored in struct @mgag200_crtc_state.pixpllc by the corresponding + * implementation of @pixpllc_atomic_check. + */ + void (*pixpllc_atomic_update)(struct drm_crtc *crtc, struct drm_atomic_state *old_state); }; struct mga_device { @@ -292,7 +294,6 @@ struct mga_device { enum mga_type type; - struct mgag200_pll pixpll; struct drm_plane primary_plane; struct drm_crtc crtc; struct drm_encoder encoder; @@ -346,11 +347,13 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); void mgag200_g200wb_init_registers(struct mga_device *mdev); +void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state); struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); void mgag200_g200eh_init_registers(struct mga_device *mdev); +void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state); struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv, @@ -372,7 +375,4 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev); /* mgag200_i2c.c */ int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c); - /* mgag200_pll.c */ -int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev); - #endif /* __MGAG200_DRV_H__ */ diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c index e11b485d470d..ae1669d208f8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c @@ -3,6 +3,7 @@ #include <linux/pci.h> #include <linux/vmalloc.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" @@ -53,6 +54,112 @@ static void mgag200_g200_init_registers(struct mgag200_g200_device *g200) mgag200_init_registers(mdev); } +/* + * PIXPLLC + */ + +static int mgag200_g200_pixpllc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state) +{ + static const int post_div_max = 7; + static const int in_div_min = 1; + static const int in_div_max = 6; + static const int feed_div_min = 7; + static const int feed_div_max = 127; + + struct drm_device *dev = crtc->dev; + struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev); + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + u8 testp, testm, testn; + u8 n = 0, m = 0, p, s; + long f_vco; + long computed; + long delta, tmp_delta; + long ref_clk = g200->ref_clk; + long p_clk_min = g200->pclk_min; + long p_clk_max = g200->pclk_max; + + if (clock > p_clk_max) { + drm_err(dev, "Pixel Clock %ld too high\n", clock); + return -EINVAL; + } + + if (clock < p_clk_min >> 3) + clock = p_clk_min >> 3; + + f_vco = clock; + for (testp = 0; + testp <= post_div_max && f_vco < p_clk_min; + testp = (testp << 1) + 1, f_vco <<= 1) + ; + p = testp + 1; + + delta = clock; + + for (testm = in_div_min; testm <= in_div_max; testm++) { + for (testn = feed_div_min; testn <= feed_div_max; testn++) { + computed = ref_clk * (testn + 1) / (testm + 1); + if (computed < f_vco) + tmp_delta = f_vco - computed; + else + tmp_delta = computed - f_vco; + if (tmp_delta < delta) { + delta = tmp_delta; + m = testm + 1; + n = testn + 1; + } + } + } + f_vco = ref_clk * n / m; + if (f_vco < 100000) + s = 0; + else if (f_vco < 140000) + s = 1; + else if (f_vco < 180000) + s = 2; + else + s = 3; + + drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", + clock, f_vco, m, n, p, s); + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void mgag200_g200_pixpllc_atomic_update(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); +} + /* * DRM Device */ @@ -184,6 +291,8 @@ out: } static const struct mgag200_device_funcs mgag200_g200_device_funcs = { + .pixpllc_atomic_check = mgag200_g200_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200_pixpllc_atomic_update, }; struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv, diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c index 473ff5217db5..fd44d19c729a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <linux/delay.h> #include <linux/pci.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" @@ -30,6 +32,133 @@ void mgag200_g200eh_init_registers(struct mga_device *mdev) mgag200_init_registers(mdev); } +/* + * PIXPLLC + */ + +static int mgag200_g200eh_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 800000; + static const unsigned int vcomin = 400000; + static const unsigned int pllreffreq = 33333; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 16; testp > 0; testp >>= 1) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testm = 1; testm < 33; testm++) { + for (testn = 17; testn < 257; testn++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn; + m = testm; + p = testp; + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + int i, j, tmpcount, vcount; + bool pll_locked = false; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + for (i = 0; i <= 32 && pll_locked == false; i++) { + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= 0x3 << 2; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + udelay(500); + + WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp); + + udelay(500); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + vcount = RREG8(MGAREG_VCOUNT); + + for (j = 0; j < 30 && pll_locked == false; j++) { + tmpcount = RREG8(MGAREG_VCOUNT); + if (tmpcount < vcount) + vcount = 0; + if ((tmpcount - vcount) > 2) + pll_locked = true; + else + udelay(5); + } + } +} + /* * DRM device */ @@ -38,6 +167,8 @@ static const struct mgag200_device_info mgag200_g200eh_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false, 1, 0, false); static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = { + .pixpllc_atomic_check = mgag200_g200eh_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, }; struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c index 99e00aa848e1..b47b100d219d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c @@ -2,10 +2,67 @@ #include <linux/pci.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" +/* + * PIXPLLC + */ + +static int mgag200_g200eh3_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 3000000; + static const unsigned int vcomin = 1500000; + static const unsigned int pllreffreq = 25000; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + testp = 0; + + for (testm = 150; testm >= 6; testm--) { + if (clock * testm > vcomax) + continue; + if (clock * testm < vcomin) + continue; + for (testn = 120; testn >= 60; testn--) { + computed = (pllreffreq * testn) / testm; + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn + 1; + m = testm + 1; + p = testp + 1; + } + if (delta == 0) + break; + } + if (delta == 0) + break; + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + /* * DRM device */ @@ -14,6 +71,8 @@ static const struct mgag200_device_info mgag200_g200eh3_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false, 1, 0, false); static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = { + .pixpllc_atomic_check = mgag200_g200eh3_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, // same as G200EH }; struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 1c9a963dd9c5..8a85fd034e3d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <linux/delay.h> #include <linux/pci.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" @@ -31,6 +33,122 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev) WREG_ECRT(0x24, 0x5); /* G200ER specific */ } +/* + * PIXPLLC + */ + +static int mgag200_g200er_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 1488000; + static const unsigned int vcomin = 1056000; + static const unsigned int pllreffreq = 48000; + static const unsigned int m_div_val[] = { 1, 2, 4, 8 }; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta; + int testr, testn, testm, testo; + unsigned int p, m, n, s; + unsigned int computed, vco; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testr = 0; testr < 4; testr++) { + if (delta == 0) + break; + for (testn = 5; testn < 129; testn++) { + if (delta == 0) + break; + for (testm = 3; testm >= 0; testm--) { + if (delta == 0) + break; + for (testo = 5; testo < 33; testo++) { + vco = pllreffreq * (testn + 1) / + (testr + 1); + if (vco < vcomin) + continue; + if (vco > vcomax) + continue; + computed = vco / (m_div_val[testm] * (testo + 1)); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + m = (testm | (testo << 3)) + 1; + n = testn + 1; + p = testr + 1; + s = testr; + } + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void mgag200_g200er_pixpllc_atomic_update(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_REMHEADCTL_CLKDIS; + WREG8(DAC_DATA, tmp); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= (0x3<<2) | 0xc0; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + udelay(500); + + WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp); + + udelay(50); +} + /* * DRM device */ @@ -39,6 +157,8 @@ static const struct mgag200_device_info mgag200_g200er_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 1, 0, false); static const struct mgag200_device_funcs mgag200_g200er_device_funcs = { + .pixpllc_atomic_check = mgag200_g200er_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200er_pixpllc_atomic_update, }; struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv, diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index a0dc72a69f52..54c80562900d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <linux/delay.h> #include <linux/pci.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" @@ -31,6 +33,134 @@ static void mgag200_g200ev_init_registers(struct mga_device *mdev) mgag200_init_registers(mdev); } +/* + * PIXPLLC + */ + +static int mgag200_g200ev_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 550000; + static const unsigned int vcomin = 150000; + static const unsigned int pllreffreq = 50000; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 16; testp > 0; testp--) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testn = 1; testn < 257; testn++) { + for (testm = 1; testm < 17; testm++) { + computed = (pllreffreq * testn) / + (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn; + m = testm; + p = testp; + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void mgag200_g200ev_pixpllc_atomic_update(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= 0x3 << 2; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); + tmp = RREG8(DAC_DATA); + WREG8(DAC_DATA, tmp & ~0x40); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp); + + udelay(50); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + udelay(500); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); + tmp = RREG8(DAC_DATA); + WREG8(DAC_DATA, tmp | 0x40); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= (0x3 << 2); + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); +} + /* * DRM device */ @@ -39,6 +169,8 @@ static const struct mgag200_device_info mgag200_g200ev_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false, 0, 1, false); static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = { + .pixpllc_atomic_check = mgag200_g200ev_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200ev_pixpllc_atomic_update, }; struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index 19a870120ebc..29aa8a3d4522 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -2,6 +2,7 @@ #include <linux/pci.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" @@ -13,6 +14,64 @@ static void mgag200_g200ew3_init_registers(struct mga_device *mdev) WREG_ECRT(0x34, 0x5); // G200EW3 specific } +/* + * PIXPLLC + */ + +static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 800000; + static const unsigned int vcomin = 400000; + static const unsigned int pllreffreq = 25000; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn, testp2; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 1; testp < 8; testp++) { + for (testp2 = 1; testp2 < 8; testp2++) { + if (testp < testp2) + continue; + if ((clock * testp * testp2) > vcomax) + continue; + if ((clock * testp * testp2) < vcomin) + continue; + for (testm = 1; testm < 26; testm++) { + for (testn = 32; testn < 2048 ; testn++) { + computed = (pllreffreq * testn) / (testm * testp * testp2); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + m = testm + 1; + n = testn + 1; + p = testp + 1; + s = testp2; + } + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + /* * DRM device */ @@ -23,6 +82,8 @@ static const struct mgag200_device_info mgag200_g200ew3_device_info = static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = { .disable_vidrst = mgag200_bmc_disable_vidrst, .enable_vidrst = mgag200_bmc_enable_vidrst, + .pixpllc_atomic_check = mgag200_g200ew3_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, // same as G200WB }; static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev) diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index 7a7648d7de93..ca9ea26219ca 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <linux/delay.h> #include <linux/pci.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" @@ -56,6 +58,198 @@ static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se) mgag200_init_registers(mdev); } +/* + * PIXPLLC + */ + +static int mgag200_g200se_00_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 320000; + static const unsigned int vcomin = 160000; + static const unsigned int pllreffreq = 25000; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta, permitteddelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + permitteddelta = clock * 5 / 1000; + + for (testp = 8; testp > 0; testp /= 2) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testn = 17; testn < 256; testn++) { + for (testm = 1; testm < 32; testm++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + m = testm; + n = testn; + p = testp; + } + } + } + } + + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void mgag200_g200se_00_pixpllc_atomic_update(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); +} + +static int mgag200_g200se_04_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 1600000; + static const unsigned int vcomin = 800000; + static const unsigned int pllreffreq = 25000; + static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1}; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta, permitteddelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + unsigned int fvv; + unsigned int i; + + m = n = p = s = 0; + delta = 0xffffffff; + + if (clock < 25000) + clock = 25000; + clock = clock * 2; + + /* Permited delta is 0.5% as VESA Specification */ + permitteddelta = clock * 5 / 1000; + + for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) { + testp = pvalues_e4[i]; + + if ((clock * testp) > vcomax) + continue; + if ((clock * testp) < vcomin) + continue; + + for (testn = 50; testn <= 256; testn++) { + for (testm = 1; testm <= 32; testm++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + + if (tmpdelta < delta) { + delta = tmpdelta; + m = testm; + n = testn; + p = testp; + } + } + } + } + + fvv = pllreffreq * n / m; + fvv = (fvv - 800000) / 50000; + if (fvv > 15) + fvv = 15; + s = fvv << 1; + + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); + + WREG_DAC(0x1a, 0x09); + msleep(20); + WREG_DAC(0x1a, 0x01); +} + /* * DRM device */ @@ -93,7 +287,14 @@ static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200s return 0; } -static const struct mgag200_device_funcs mgag200_g200se_device_funcs = { +static const struct mgag200_device_funcs mgag200_g200se_00_device_funcs = { + .pixpllc_atomic_check = mgag200_g200se_00_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200se_00_pixpllc_atomic_update, +}; + +static const struct mgag200_device_funcs mgag200_g200se_04_device_funcs = { + .pixpllc_atomic_check = mgag200_g200se_04_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200se_04_pixpllc_atomic_update, }; struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, @@ -101,6 +302,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru { struct mgag200_g200se_device *g200se; const struct mgag200_device_info *info; + const struct mgag200_device_funcs *funcs; struct mga_device *mdev; struct drm_device *dev; resource_size_t vram_available; @@ -147,7 +349,12 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru return ERR_PTR(-EINVAL); } - ret = mgag200_device_init(mdev, type, info, &mgag200_g200se_device_funcs); + if (g200se->unique_rev_id >= 0x04) + funcs = &mgag200_g200se_04_device_funcs; + else + funcs = &mgag200_g200se_00_device_funcs; + + ret = mgag200_device_init(mdev, type, info, funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index 91d2848b4b06..1e0c80c2787d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <linux/delay.h> #include <linux/pci.h> +#include <drm/drm_atomic.h> #include <drm/drm_drv.h> #include "mgag200_drv.h" @@ -28,6 +30,182 @@ void mgag200_g200wb_init_registers(struct mga_device *mdev) mgag200_init_registers(mdev); } +/* + * PIXPLLC + */ + +static int mgag200_g200wb_pixpllc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + static const unsigned int vcomax = 550000; + static const unsigned int vcomin = 150000; + static const unsigned int pllreffreq = 48000; + + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); + long clock = new_crtc_state->mode.clock; + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 1; testp < 9; testp++) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testm = 1; testm < 17; testm++) { + for (testn = 1; testn < 151; testn++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn; + m = testm; + p = testp; + s = 0; + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; + bool pll_locked = false; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + int i, j, tmpcount, vcount; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + for (i = 0; i <= 32 && pll_locked == false; i++) { + if (i > 0) { + WREG8(MGAREG_CRTC_INDEX, 0x1e); + tmp = RREG8(MGAREG_CRTC_DATA); + if (tmp < 0xff) + WREG8(MGAREG_CRTC_DATA, tmp+1); + } + + /* set pixclkdis to 1 */ + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_REMHEADCTL_CLKDIS; + WREG8(DAC_DATA, tmp); + + /* select PLL Set C */ + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= 0x3 << 2; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; + WREG8(DAC_DATA, tmp); + + udelay(500); + + /* reset the PLL */ + WREG8(DAC_INDEX, MGA1064_VREF_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~0x04; + WREG8(DAC_DATA, tmp); + + udelay(50); + + /* program pixel pll register */ + 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); + + /* turn pll on */ + WREG8(DAC_INDEX, MGA1064_VREF_CTL); + tmp = RREG8(DAC_DATA); + tmp |= 0x04; + WREG_DAC(MGA1064_VREF_CTL, tmp); + + udelay(500); + + /* select the pixel pll */ + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; + tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; + WREG8(DAC_DATA, tmp); + + /* reset dotclock rate bit */ + WREG8(MGAREG_SEQ_INDEX, 1); + tmp = RREG8(MGAREG_SEQ_DATA); + tmp &= ~0x8; + WREG8(MGAREG_SEQ_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + vcount = RREG8(MGAREG_VCOUNT); + + for (j = 0; j < 30 && pll_locked == false; j++) { + tmpcount = RREG8(MGAREG_VCOUNT); + if (tmpcount < vcount) + vcount = 0; + if ((tmpcount - vcount) > 2) + pll_locked = true; + else + udelay(5); + } + } + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_REMHEADCTL_CLKDIS; + WREG_DAC(MGA1064_REMHEADCTL, tmp); +} + /* * DRM device */ @@ -38,6 +216,8 @@ static const struct mgag200_device_info mgag200_g200wb_device_info = static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = { .disable_vidrst = mgag200_bmc_disable_vidrst, .enable_vidrst = mgag200_bmc_enable_vidrst, + .pixpllc_atomic_check = mgag200_g200wb_pixpllc_atomic_check, + .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, }; struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 2b1e9f069366..d999673e0278 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -660,9 +660,8 @@ static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct mga_device *mdev = to_mga_device(dev); + const struct mgag200_device_funcs *funcs = mdev->funcs; struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); - struct mgag200_pll *pixpll = &mdev->pixpll; - struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut; int ret; @@ -674,10 +673,11 @@ static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, return 0; if (new_crtc_state->mode_changed) { - ret = pixpll->funcs->compute(pixpll, new_crtc_state->mode.clock, - &mgag200_crtc_state->pixpllc); - if (ret) - return ret; + if (funcs->pixpllc_atomic_check) { + ret = funcs->pixpllc_atomic_check(crtc, new_state); + if (ret) + return ret; + } } if (new_crtc_state->color_mgmt_changed && new_gamma_lut) { @@ -718,7 +718,6 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); const struct drm_format_info *format = mgag200_crtc_state->format; - struct mgag200_pll *pixpll = &mdev->pixpll; if (funcs->disable_vidrst) funcs->disable_vidrst(mdev); @@ -726,7 +725,8 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_set_format_regs(mdev, format); mgag200_set_mode_regs(mdev, adjusted_mode); - pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc); + if (funcs->pixpllc_atomic_update) + funcs->pixpllc_atomic_update(crtc, old_state); if (mdev->type == G200_ER) mgag200_g200er_reset_tagfifo(mdev); @@ -976,10 +976,6 @@ static int mgag200_pipeline_init(struct mga_device *mdev) struct drm_connector *connector = &mdev->connector; int ret; - ret = mgag200_pixpll_init(&mdev->pixpll, mdev); - if (ret) - return ret; - ret = drm_universal_plane_init(dev, primary_plane, 0, &mgag200_primary_plane_funcs, mgag200_primary_plane_formats, diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c deleted file mode 100644 index 8065ca5d8de9..000000000000 --- a/drivers/gpu/drm/mgag200/mgag200_pll.c +++ /dev/null @@ -1,997 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include <linux/delay.h> - -#include "mgag200_drv.h" - -/* - * G200 - */ - -static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - struct mga_device *mdev = pixpll->mdev; - struct drm_device *dev = &mdev->base; - struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev); - const int post_div_max = 7; - const int in_div_min = 1; - const int in_div_max = 6; - const int feed_div_min = 7; - const int feed_div_max = 127; - u8 testp, testm, testn; - u8 n = 0, m = 0, p, s; - long f_vco; - long computed; - long delta, tmp_delta; - long ref_clk = g200->ref_clk; - long p_clk_min = g200->pclk_min; - long p_clk_max = g200->pclk_max; - - if (clock > p_clk_max) { - drm_err(dev, "Pixel Clock %ld too high\n", clock); - return -EINVAL; - } - - if (clock < p_clk_min >> 3) - clock = p_clk_min >> 3; - - f_vco = clock; - for (testp = 0; - testp <= post_div_max && f_vco < p_clk_min; - testp = (testp << 1) + 1, f_vco <<= 1) - ; - p = testp + 1; - - delta = clock; - - for (testm = in_div_min; testm <= in_div_max; testm++) { - for (testn = feed_div_min; testn <= feed_div_max; testn++) { - computed = ref_clk * (testn + 1) / (testm + 1); - if (computed < f_vco) - tmp_delta = f_vco - computed; - else - tmp_delta = computed - f_vco; - if (tmp_delta < delta) { - delta = tmp_delta; - m = testm + 1; - n = testn + 1; - } - } - } - f_vco = ref_clk * n / m; - if (f_vco < 100000) - s = 0; - else if (f_vco < 140000) - s = 1; - else if (f_vco < 180000) - s = 2; - else - s = 3; - - drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", - clock, f_vco, m, n, p, s); - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static void -mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) -{ - struct mga_device *mdev = pixpll->mdev; - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; - u8 xpixpllcm, xpixpllcn, xpixpllcp; - - pixpllcm = pixpllc->m - 1; - pixpllcn = pixpllc->n - 1; - pixpllcp = pixpllc->p - 1; - pixpllcs = pixpllc->s; - - xpixpllcm = pixpllcm; - xpixpllcn = pixpllcn; - xpixpllcp = (pixpllcs << 3) | pixpllcp; - - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); - - WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); - WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); - WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = { - .compute = mgag200_pixpll_compute_g200, - .update = mgag200_pixpll_update_g200, -}; - -/* - * G200SE - */ - -static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 320000; - static const unsigned int vcomin = 160000; - static const unsigned int pllreffreq = 25000; - - unsigned int delta, tmpdelta, permitteddelta; - unsigned int testp, testm, testn; - unsigned int p, m, n, s; - unsigned int computed; - - m = n = p = s = 0; - delta = 0xffffffff; - permitteddelta = clock * 5 / 1000; - - for (testp = 8; testp > 0; testp /= 2) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testn = 17; testn < 256; testn++) { - for (testm = 1; testm < 32; testm++) { - computed = (pllreffreq * testn) / (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - m = testm; - n = testn; - p = testp; - } - } - } - } - - if (delta > permitteddelta) { - pr_warn("PLL delta too large\n"); - return -EINVAL; - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll, - const struct mgag200_pll_values *pixpllc) -{ - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; - u8 xpixpllcm, xpixpllcn, xpixpllcp; - struct mga_device *mdev = pixpll->mdev; - - pixpllcm = pixpllc->m - 1; - pixpllcn = pixpllc->n - 1; - pixpllcp = pixpllc->p - 1; - pixpllcs = pixpllc->s; - - xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); - xpixpllcn = pixpllcn; - xpixpllcp = (pixpllcs << 3) | pixpllcp; - - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); - - WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); - WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); - WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); -} - -static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 1600000; - static const unsigned int vcomin = 800000; - static const unsigned int pllreffreq = 25000; - static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1}; - - unsigned int delta, tmpdelta, permitteddelta; - unsigned int testp, testm, testn; - unsigned int p, m, n, s; - unsigned int computed; - unsigned int fvv; - unsigned int i; - - m = n = p = s = 0; - delta = 0xffffffff; - - if (clock < 25000) - clock = 25000; - clock = clock * 2; - - /* Permited delta is 0.5% as VESA Specification */ - permitteddelta = clock * 5 / 1000; - - for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) { - testp = pvalues_e4[i]; - - if ((clock * testp) > vcomax) - continue; - if ((clock * testp) < vcomin) - continue; - - for (testn = 50; testn <= 256; testn++) { - for (testm = 1; testm <= 32; testm++) { - computed = (pllreffreq * testn) / (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - - if (tmpdelta < delta) { - delta = tmpdelta; - m = testm; - n = testn; - p = testp; - } - } - } - } - - fvv = pllreffreq * n / m; - fvv = (fvv - 800000) / 50000; - if (fvv > 15) - fvv = 15; - s = fvv << 1; - - if (delta > permitteddelta) { - pr_warn("PLL delta too large\n"); - return -EINVAL; - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll, - const struct mgag200_pll_values *pixpllc) -{ - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; - u8 xpixpllcm, xpixpllcn, xpixpllcp; - struct mga_device *mdev = pixpll->mdev; - - pixpllcm = pixpllc->m - 1; - pixpllcn = pixpllc->n - 1; - pixpllcp = pixpllc->p - 1; - pixpllcs = pixpllc->s; - - xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); - xpixpllcn = pixpllcn; - xpixpllcp = (pixpllcs << 3) | pixpllcp; - - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); - - WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); - WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); - WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); - - WREG_DAC(0x1a, 0x09); - msleep(20); - WREG_DAC(0x1a, 0x01); -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = { - .compute = mgag200_pixpll_compute_g200se_00, - .update = mgag200_pixpll_update_g200se_00, -}; - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = { - .compute = mgag200_pixpll_compute_g200se_04, - .update = mgag200_pixpll_update_g200se_04, -}; - -/* - * G200WB - */ - -static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 550000; - static const unsigned int vcomin = 150000; - static const unsigned int pllreffreq = 48000; - - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn; - unsigned int p, m, n, s; - unsigned int computed; - - m = n = p = s = 0; - delta = 0xffffffff; - - for (testp = 1; testp < 9; testp++) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testm = 1; testm < 17; testm++) { - for (testn = 1; testn < 151; testn++) { - computed = (pllreffreq * testn) / (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn; - m = testm; - p = testp; - s = 0; - } - } - } - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static void -mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) -{ - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; - int i, j, tmpcount, vcount; - struct mga_device *mdev = pixpll->mdev; - bool pll_locked = false; - - pixpllcm = pixpllc->m - 1; - pixpllcn = pixpllc->n - 1; - pixpllcp = pixpllc->p - 1; - pixpllcs = pixpllc->s; - - xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; - xpixpllcn = pixpllcn; - xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp; - - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); - - for (i = 0; i <= 32 && pll_locked == false; i++) { - if (i > 0) { - WREG8(MGAREG_CRTC_INDEX, 0x1e); - tmp = RREG8(MGAREG_CRTC_DATA); - if (tmp < 0xff) - WREG8(MGAREG_CRTC_DATA, tmp+1); - } - - /* set pixclkdis to 1 */ - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_REMHEADCTL_CLKDIS; - WREG8(DAC_DATA, tmp); - - /* select PLL Set C */ - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= 0x3 << 2; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; - WREG8(DAC_DATA, tmp); - - udelay(500); - - /* reset the PLL */ - WREG8(DAC_INDEX, MGA1064_VREF_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~0x04; - WREG8(DAC_DATA, tmp); - - udelay(50); - - /* program pixel pll register */ - 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); - - /* turn pll on */ - WREG8(DAC_INDEX, MGA1064_VREF_CTL); - tmp = RREG8(DAC_DATA); - tmp |= 0x04; - WREG_DAC(MGA1064_VREF_CTL, tmp); - - udelay(500); - - /* select the pixel pll */ - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; - tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; - WREG8(DAC_DATA, tmp); - - /* reset dotclock rate bit */ - WREG8(MGAREG_SEQ_INDEX, 1); - tmp = RREG8(MGAREG_SEQ_DATA); - tmp &= ~0x8; - WREG8(MGAREG_SEQ_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - vcount = RREG8(MGAREG_VCOUNT); - - for (j = 0; j < 30 && pll_locked == false; j++) { - tmpcount = RREG8(MGAREG_VCOUNT); - if (tmpcount < vcount) - vcount = 0; - if ((tmpcount - vcount) > 2) - pll_locked = true; - else - udelay(5); - } - } - - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_REMHEADCTL_CLKDIS; - WREG_DAC(MGA1064_REMHEADCTL, tmp); -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = { - .compute = mgag200_pixpll_compute_g200wb, - .update = mgag200_pixpll_update_g200wb, -}; - -/* - * G200EV - */ - -static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 550000; - static const unsigned int vcomin = 150000; - static const unsigned int pllreffreq = 50000; - - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn; - unsigned int p, m, n, s; - unsigned int computed; - - m = n = p = s = 0; - delta = 0xffffffff; - - for (testp = 16; testp > 0; testp--) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testn = 1; testn < 257; testn++) { - for (testm = 1; testm < 17; testm++) { - computed = (pllreffreq * testn) / - (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn; - m = testm; - p = testp; - } - } - } - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static void -mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) -{ - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; - struct mga_device *mdev = pixpll->mdev; - - pixpllcm = pixpllc->m - 1; - pixpllcn = pixpllc->n - 1; - pixpllcp = pixpllc->p - 1; - pixpllcs = pixpllc->s; - - xpixpllcm = pixpllcm; - xpixpllcn = pixpllcn; - xpixpllcp = (pixpllcs << 3) | pixpllcp; - - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= 0x3 << 2; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); - tmp = RREG8(DAC_DATA); - WREG8(DAC_DATA, tmp & ~0x40); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm); - WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn); - WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp); - - udelay(50); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - udelay(500); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); - tmp = RREG8(DAC_DATA); - WREG8(DAC_DATA, tmp | 0x40); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= (0x3 << 2); - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = { - .compute = mgag200_pixpll_compute_g200ev, - .update = mgag200_pixpll_update_g200ev, -}; - -/* - * G200EH - */ - -static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 800000; - static const unsigned int vcomin = 400000; - static const unsigned int pllreffreq = 33333; - - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn; - unsigned int p, m, n, s; - unsigned int computed; - - m = n = p = s = 0; - delta = 0xffffffff; - - for (testp = 16; testp > 0; testp >>= 1) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testm = 1; testm < 33; testm++) { - for (testn = 17; testn < 257; testn++) { - computed = (pllreffreq * testn) / (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn; - m = testm; - p = testp; - } - } - } - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static void -mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) -{ - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; - int i, j, tmpcount, vcount; - struct mga_device *mdev = pixpll->mdev; - bool pll_locked = false; - - pixpllcm = pixpllc->m - 1; - pixpllcn = pixpllc->n - 1; - pixpllcp = pixpllc->p - 1; - pixpllcs = pixpllc->s; - - xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; - xpixpllcn = pixpllcn; - xpixpllcp = (pixpllcs << 3) | pixpllcp; - - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); - - for (i = 0; i <= 32 && pll_locked == false; i++) { - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= 0x3 << 2; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - udelay(500); - - WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm); - WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn); - WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp); - - udelay(500); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - vcount = RREG8(MGAREG_VCOUNT); - - for (j = 0; j < 30 && pll_locked == false; j++) { - tmpcount = RREG8(MGAREG_VCOUNT); - if (tmpcount < vcount) - vcount = 0; - if ((tmpcount - vcount) > 2) - pll_locked = true; - else - udelay(5); - } - } -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = { - .compute = mgag200_pixpll_compute_g200eh, - .update = mgag200_pixpll_update_g200eh, -}; - -/* - * G200EH3 - */ - -static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 3000000; - static const unsigned int vcomin = 1500000; - static const unsigned int pllreffreq = 25000; - - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn; - unsigned int p, m, n, s; - unsigned int computed; - - m = n = p = s = 0; - delta = 0xffffffff; - testp = 0; - - for (testm = 150; testm >= 6; testm--) { - if (clock * testm > vcomax) - continue; - if (clock * testm < vcomin) - continue; - for (testn = 120; testn >= 60; testn--) { - computed = (pllreffreq * testn) / testm; - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn + 1; - m = testm + 1; - p = testp + 1; - } - if (delta == 0) - break; - } - if (delta == 0) - break; - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = { - .compute = mgag200_pixpll_compute_g200eh3, - .update = mgag200_pixpll_update_g200eh, // same as G200EH -}; - -/* - * G200ER - */ - -static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 1488000; - static const unsigned int vcomin = 1056000; - static const unsigned int pllreffreq = 48000; - static const unsigned int m_div_val[] = { 1, 2, 4, 8 }; - - unsigned int delta, tmpdelta; - int testr, testn, testm, testo; - unsigned int p, m, n, s; - unsigned int computed, vco; - - m = n = p = s = 0; - delta = 0xffffffff; - - for (testr = 0; testr < 4; testr++) { - if (delta == 0) - break; - for (testn = 5; testn < 129; testn++) { - if (delta == 0) - break; - for (testm = 3; testm >= 0; testm--) { - if (delta == 0) - break; - for (testo = 5; testo < 33; testo++) { - vco = pllreffreq * (testn + 1) / - (testr + 1); - if (vco < vcomin) - continue; - if (vco > vcomax) - continue; - computed = vco / (m_div_val[testm] * (testo + 1)); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - m = (testm | (testo << 3)) + 1; - n = testn + 1; - p = testr + 1; - s = testr; - } - } - } - } - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static void -mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) -{ - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; - struct mga_device *mdev = pixpll->mdev; - - pixpllcm = pixpllc->m - 1; - pixpllcn = pixpllc->n - 1; - pixpllcp = pixpllc->p - 1; - pixpllcs = pixpllc->s; - - xpixpllcm = pixpllcm; - xpixpllcn = pixpllcn; - xpixpllcp = (pixpllcs << 3) | pixpllcp; - - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_REMHEADCTL_CLKDIS; - WREG8(DAC_DATA, tmp); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= (0x3<<2) | 0xc0; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - udelay(500); - - WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn); - WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm); - WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp); - - udelay(50); -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = { - .compute = mgag200_pixpll_compute_g200er, - .update = mgag200_pixpll_update_g200er, -}; - -/* - * G200EW3 - */ - -static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock, - struct mgag200_pll_values *pixpllc) -{ - static const unsigned int vcomax = 800000; - static const unsigned int vcomin = 400000; - static const unsigned int pllreffreq = 25000; - - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn, testp2; - unsigned int p, m, n, s; - unsigned int computed; - - m = n = p = s = 0; - delta = 0xffffffff; - - for (testp = 1; testp < 8; testp++) { - for (testp2 = 1; testp2 < 8; testp2++) { - if (testp < testp2) - continue; - if ((clock * testp * testp2) > vcomax) - continue; - if ((clock * testp * testp2) < vcomin) - continue; - for (testm = 1; testm < 26; testm++) { - for (testn = 32; testn < 2048 ; testn++) { - computed = (pllreffreq * testn) / (testm * testp * testp2); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - m = testm + 1; - n = testn + 1; - p = testp + 1; - s = testp2; - } - } - } - } - } - - pixpllc->m = m; - pixpllc->n = n; - pixpllc->p = p; - pixpllc->s = s; - - return 0; -} - -static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = { - .compute = mgag200_pixpll_compute_g200ew3, - .update = mgag200_pixpll_update_g200wb, // same as G200WB -}; - -/* - * PLL initialization - */ - -int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev) -{ - struct drm_device *dev = &mdev->base; - struct mgag200_g200se_device *g200se; - - pixpll->mdev = mdev; - - switch (mdev->type) { - case G200_PCI: - case G200_AGP: - pixpll->funcs = &mgag200_pixpll_funcs_g200; - break; - case G200_SE_A: - case G200_SE_B: - g200se = to_mgag200_g200se_device(dev); - - if (g200se->unique_rev_id >= 0x04) - pixpll->funcs = &mgag200_pixpll_funcs_g200se_04; - else - pixpll->funcs = &mgag200_pixpll_funcs_g200se_00; - break; - case G200_WB: - pixpll->funcs = &mgag200_pixpll_funcs_g200wb; - break; - case G200_EV: - pixpll->funcs = &mgag200_pixpll_funcs_g200ev; - break; - case G200_EH: - pixpll->funcs = &mgag200_pixpll_funcs_g200eh; - break; - case G200_EH3: - pixpll->funcs = &mgag200_pixpll_funcs_g200eh3; - break; - case G200_ER: - pixpll->funcs = &mgag200_pixpll_funcs_g200er; - break; - case G200_EW3: - pixpll->funcs = &mgag200_pixpll_funcs_g200ew3; - break; - default: - drm_err(dev, "unknown device type %d\n", mdev->type); - return -ENODEV; - } - - return 0; -} From bc8350409ca5147d432f869209ee13fa079625df Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:41:01 +0200 Subject: [PATCH 234/396] drm/mgag200: Move mode-config to model-specific code Move the mode-config code into model-specific code and call the plane/CRTC helpers as needed. This will help with providing per- model implementations of individual helpers. Duplication of the pipeline init function is accepted. Some macros simplify this for shared helpers. v3: * clean up style Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-13-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.h | 78 ++++++++- drivers/gpu/drm/mgag200/mgag200_g200.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200eh.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200er.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200se.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200wb.c | 111 ++++++++++++- drivers/gpu/drm/mgag200/mgag200_mode.c | 185 +++------------------- 10 files changed, 977 insertions(+), 174 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index cc14028df395..1e7de8b12e75 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -152,6 +152,8 @@ /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, \ /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 \ +#define MGAG200_LUT_SIZE 256 + #define MGAG200_MAX_FB_HEIGHT 4096 #define MGAG200_MAX_FB_WIDTH 4096 @@ -363,10 +365,82 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); - /* mgag200_mode.c */ +/* + * mgag200_mode.c + */ + +struct drm_crtc; +struct drm_crtc_state; +struct drm_display_mode; +struct drm_plane; +struct drm_atomic_state; + +extern const uint32_t mgag200_primary_plane_formats[]; +extern const size_t mgag200_primary_plane_formats_size; +extern const uint64_t mgag200_primary_plane_fmtmods[]; + +int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *new_state); +void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *old_state); +void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *old_state); +#define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \ + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \ + .atomic_check = mgag200_primary_plane_helper_atomic_check, \ + .atomic_update = mgag200_primary_plane_helper_atomic_update, \ + .atomic_disable = mgag200_primary_plane_helper_atomic_disable + +#define MGAG200_PRIMARY_PLANE_FUNCS \ + .update_plane = drm_atomic_helper_update_plane, \ + .disable_plane = drm_atomic_helper_disable_plane, \ + .destroy = drm_plane_cleanup, \ + DRM_GEM_SHADOW_PLANE_FUNCS + +enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode); +int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state); +void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state); +void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *old_state); +void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state); + +#define MGAG200_CRTC_HELPER_FUNCS \ + .mode_valid = mgag200_crtc_helper_mode_valid, \ + .atomic_check = mgag200_crtc_helper_atomic_check, \ + .atomic_flush = mgag200_crtc_helper_atomic_flush, \ + .atomic_enable = mgag200_crtc_helper_atomic_enable, \ + .atomic_disable = mgag200_crtc_helper_atomic_disable + +void mgag200_crtc_reset(struct drm_crtc *crtc); +struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc); +void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state); + +#define MGAG200_CRTC_FUNCS \ + .reset = mgag200_crtc_reset, \ + .destroy = drm_crtc_cleanup, \ + .set_config = drm_atomic_helper_set_config, \ + .page_flip = drm_atomic_helper_page_flip, \ + .atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, \ + .atomic_destroy_state = mgag200_crtc_atomic_destroy_state + +#define MGAG200_DAC_ENCODER_FUNCS \ + .destroy = drm_encoder_cleanup + +int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector); + +#define MGAG200_VGA_CONNECTOR_HELPER_FUNCS \ + .get_modes = mgag200_vga_connector_helper_get_modes + +#define MGAG200_VGA_CONNECTOR_FUNCS \ + .reset = drm_atomic_helper_connector_reset, \ + .fill_modes = drm_helper_probe_single_connector_modes, \ + .destroy = drm_connector_cleanup, \ + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \ + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state + resource_size_t mgag200_device_probe_vram(struct mga_device *mdev); void mgag200_init_registers(struct mga_device *mdev); -int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available); +int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available); /* mgag200_bmc.c */ void mgag200_bmc_disable_vidrst(struct mga_device *mdev); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c index ae1669d208f8..dffcfa83ae74 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c @@ -4,7 +4,10 @@ #include <linux/vmalloc.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -160,6 +163,106 @@ static void mgag200_g200_pixpllc_atomic_update(struct drm_crtc *crtc, WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM Device */ @@ -331,9 +434,15 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct vram_available = mgag200_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c index fd44d19c729a..54568d1f603a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c @@ -4,7 +4,10 @@ #include <linux/pci.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -159,6 +162,106 @@ void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, } } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200eh_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200eh_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200eh_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200eh_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200eh_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200eh_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200eh_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200eh_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200eh_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200eh_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200eh_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200eh_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200eh_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200eh_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200eh_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM device */ @@ -203,9 +306,15 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru vram_available = mgag200_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200eh_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c index b47b100d219d..3e2929fd6145 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c @@ -3,7 +3,10 @@ #include <linux/pci.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -63,6 +66,106 @@ static int mgag200_g200eh3_pixpllc_atomic_check(struct drm_crtc *crtc, return 0; } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200eh3_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200eh3_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200eh3_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200eh3_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200eh3_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200eh3_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200eh3_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200eh3_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200eh3_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200eh3_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200eh3_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200eh3_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200eh3_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200eh3_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM device */ @@ -108,9 +211,15 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, vram_available = mgag200_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200eh3_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 8a85fd034e3d..399f2443cb47 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -4,7 +4,10 @@ #include <linux/pci.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -149,6 +152,106 @@ static void mgag200_g200er_pixpllc_atomic_update(struct drm_crtc *crtc, udelay(50); } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200er_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200er_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200er_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200er_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200er_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200er_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200er_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200er_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200er_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200er_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200er_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200er_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200er_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM device */ @@ -189,9 +292,15 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru vram_available = mgag200_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200er_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index 54c80562900d..2165ec7d63e8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -4,7 +4,10 @@ #include <linux/pci.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -161,6 +164,106 @@ static void mgag200_g200ev_pixpllc_atomic_update(struct drm_crtc *crtc, WREG8(DAC_DATA, tmp); } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200ev_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200ev_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200ev_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200ev_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200ev_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200ev_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200ev_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200ev_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200ev_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200ev_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200ev_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200ev_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200ev_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200ev_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM device */ @@ -205,9 +308,15 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru vram_available = mgag200_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200ev_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index 29aa8a3d4522..25b7bce31e0b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -3,7 +3,10 @@ #include <linux/pci.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -72,6 +75,106 @@ static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc, return 0; } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200ew3_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200ew3_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200ew3_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200ew3_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200ew3_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200ew3_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200ew3_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200ew3_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200ew3_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200ew3_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200ew3_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200ew3_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200ew3_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM device */ @@ -128,9 +231,15 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, vram_available = mgag200_g200ew3_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200ew3_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index ca9ea26219ca..a28f5203a95a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -4,7 +4,10 @@ #include <linux/pci.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -250,6 +253,106 @@ static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc, WREG_DAC(0x1a, 0x01); } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200se_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200se_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200se_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200se_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200se_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200se_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200se_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200se_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200se_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200se_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200se_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200se_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200se_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM device */ @@ -362,9 +465,15 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru vram_available = mgag200_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200se_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index 1e0c80c2787d..01d21b6a4ce9 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -4,7 +4,10 @@ #include <linux/pci.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_probe_helper.h> #include "mgag200_drv.h" @@ -206,6 +209,106 @@ void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, WREG_DAC(MGA1064_REMHEADCTL, tmp); } +/* + * Mode-setting pipeline + */ + +static const struct drm_plane_helper_funcs mgag200_g200wb_primary_plane_helper_funcs = { + MGAG200_PRIMARY_PLANE_HELPER_FUNCS, +}; + +static const struct drm_plane_funcs mgag200_g200wb_primary_plane_funcs = { + MGAG200_PRIMARY_PLANE_FUNCS, +}; + +static const struct drm_crtc_helper_funcs mgag200_g200wb_crtc_helper_funcs = { + MGAG200_CRTC_HELPER_FUNCS, +}; + +static const struct drm_crtc_funcs mgag200_g200wb_crtc_funcs = { + MGAG200_CRTC_FUNCS, +}; + +static const struct drm_encoder_funcs mgag200_g200wb_dac_encoder_funcs = { + MGAG200_DAC_ENCODER_FUNCS, +}; + +static const struct drm_connector_helper_funcs mgag200_g200wb_vga_connector_helper_funcs = { + MGAG200_VGA_CONNECTOR_HELPER_FUNCS, +}; + +static const struct drm_connector_funcs mgag200_g200wb_vga_connector_funcs = { + MGAG200_VGA_CONNECTOR_FUNCS, +}; + +static int mgag200_g200wb_pipeline_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_plane *primary_plane = &mdev->primary_plane; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder = &mdev->encoder; + struct mga_i2c_chan *i2c = &mdev->i2c; + struct drm_connector *connector = &mdev->connector; + int ret; + + ret = drm_universal_plane_init(dev, primary_plane, 0, + &mgag200_g200wb_primary_plane_funcs, + mgag200_primary_plane_formats, + mgag200_primary_plane_formats_size, + mgag200_primary_plane_fmtmods, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(primary_plane, &mgag200_g200wb_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &mgag200_g200wb_crtc_funcs, NULL); + if (ret) { + drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); + return ret; + } + drm_crtc_helper_add(crtc, &mgag200_g200wb_crtc_helper_funcs); + + /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ + drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, &mgag200_g200wb_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + + ret = mgag200_i2c_init(mdev, i2c); + if (ret) { + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_g200wb_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &i2c->adapter); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_g200wb_vga_connector_helper_funcs); + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} + /* * DRM device */ @@ -252,9 +355,15 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru vram_available = mgag200_device_probe_vram(mdev); - ret = mgag200_modeset_init(mdev, vram_available); + ret = mgag200_mode_config_init(mdev, vram_available); if (ret) return ERR_PTR(ret); + ret = mgag200_g200wb_pipeline_init(mdev); + if (ret) + return ERR_PTR(ret); + + drm_mode_config_reset(dev); + return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index d999673e0278..789ea77b94ae 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -13,8 +13,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_atomic_state_helper.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> @@ -26,8 +24,6 @@ #include "mgag200_drv.h" -#define MGAG200_LUT_SIZE 256 - /* * This file contains setup code for the CRTC. */ @@ -515,19 +511,21 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma * Primary plane */ -static const uint32_t mgag200_primary_plane_formats[] = { +const uint32_t mgag200_primary_plane_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_RGB888, }; -static const uint64_t mgag200_primary_plane_fmtmods[] = { +const size_t mgag200_primary_plane_formats_size = ARRAY_SIZE(mgag200_primary_plane_formats); + +const uint64_t mgag200_primary_plane_fmtmods[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID }; -static int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *new_state) +int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *new_state) { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); struct drm_framebuffer *new_fb = new_plane_state->fb; @@ -561,8 +559,8 @@ static int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane, return 0; } -static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, - struct drm_atomic_state *old_state) +void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *old_state) { struct drm_device *dev = plane->dev; struct mga_device *mdev = to_mga_device(dev); @@ -594,8 +592,8 @@ static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, } } -static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, - struct drm_atomic_state *old_state) +void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *old_state) { struct drm_device *dev = plane->dev; struct mga_device *mdev = to_mga_device(dev); @@ -607,26 +605,12 @@ static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, msleep(20); } -static const struct drm_plane_helper_funcs mgag200_primary_plane_helper_funcs = { - DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, - .atomic_check = mgag200_primary_plane_helper_atomic_check, - .atomic_update = mgag200_primary_plane_helper_atomic_update, - .atomic_disable = mgag200_primary_plane_helper_atomic_disable, -}; - -static const struct drm_plane_funcs mgag200_primary_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_plane_cleanup, - DRM_GEM_SHADOW_PLANE_FUNCS, -}; - /* * CRTC */ -static enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) +enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct mga_device *mdev = to_mga_device(crtc->dev); const struct mgag200_device_info *info = mdev->info; @@ -655,8 +639,7 @@ static enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc return MODE_OK; } -static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, - struct drm_atomic_state *new_state) +int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state) { struct drm_device *dev = crtc->dev; struct mga_device *mdev = to_mga_device(dev); @@ -690,8 +673,7 @@ static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, return drm_atomic_add_affected_planes(new_state, crtc); } -static void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, - struct drm_atomic_state *old_state) +void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state) { struct drm_crtc_state *crtc_state = crtc->state; struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); @@ -708,8 +690,7 @@ static void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, } } -static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *old_state) +void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *old_state) { struct drm_device *dev = crtc->dev; struct mga_device *mdev = to_mga_device(dev); @@ -742,8 +723,7 @@ static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, funcs->enable_vidrst(mdev); } -static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, - struct drm_atomic_state *old_state) +void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state) { struct mga_device *mdev = to_mga_device(crtc->dev); const struct mgag200_device_funcs *funcs = mdev->funcs; @@ -757,15 +737,7 @@ static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, funcs->enable_vidrst(mdev); } -static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = { - .mode_valid = mgag200_crtc_helper_mode_valid, - .atomic_check = mgag200_crtc_helper_atomic_check, - .atomic_flush = mgag200_crtc_helper_atomic_flush, - .atomic_enable = mgag200_crtc_helper_atomic_enable, - .atomic_disable = mgag200_crtc_helper_atomic_disable, -}; - -static void mgag200_crtc_reset(struct drm_crtc *crtc) +void mgag200_crtc_reset(struct drm_crtc *crtc) { struct mgag200_crtc_state *mgag200_crtc_state; @@ -779,7 +751,7 @@ static void mgag200_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, NULL); } -static struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc) +struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { struct drm_crtc_state *crtc_state = crtc->state; struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); @@ -800,8 +772,7 @@ static struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crt return &new_mgag200_crtc_state->base; } -static void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *crtc_state) +void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) { struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); @@ -809,28 +780,11 @@ static void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, kfree(mgag200_crtc_state); } -static const struct drm_crtc_funcs mgag200_crtc_funcs = { - .reset = mgag200_crtc_reset, - .destroy = drm_crtc_cleanup, - .set_config = drm_atomic_helper_set_config, - .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, - .atomic_destroy_state = mgag200_crtc_atomic_destroy_state, -}; - -/* - * Encoder - */ - -static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - /* * Connector */ -static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector) +int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector) { struct mga_device *mdev = to_mga_device(connector->dev); int ret; @@ -846,18 +800,6 @@ static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connecto return ret; } -static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = { - .get_modes = mgag200_vga_connector_helper_get_modes, -}; - -static const struct drm_connector_funcs mga_vga_connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - /* * Mode config */ @@ -943,7 +885,7 @@ static const struct drm_mode_config_funcs mgag200_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available) +int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available) { struct drm_device *dev = &mdev->base; int ret; @@ -965,88 +907,3 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra return 0; } - -static int mgag200_pipeline_init(struct mga_device *mdev) -{ - struct drm_device *dev = &mdev->base; - struct drm_plane *primary_plane = &mdev->primary_plane; - struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; - int ret; - - ret = drm_universal_plane_init(dev, primary_plane, 0, - &mgag200_primary_plane_funcs, - mgag200_primary_plane_formats, - ARRAY_SIZE(mgag200_primary_plane_formats), - mgag200_primary_plane_fmtmods, - DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) { - drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); - return ret; - } - drm_plane_helper_add(primary_plane, &mgag200_primary_plane_helper_funcs); - drm_plane_enable_fb_damage_clips(primary_plane); - - ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, &mgag200_crtc_funcs, NULL); - if (ret) { - drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); - return ret; - } - drm_crtc_helper_add(crtc, &mgag200_crtc_helper_funcs); - - /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ - drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); - drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mga_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); - return ret; - } - drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs); - - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); - return ret; - } - - return 0; -} - -int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available) -{ - struct drm_device *dev = &mdev->base; - int ret; - - ret = mgag200_mode_config_init(mdev, vram_available); - if (ret) - return ret; - - ret = mgag200_pipeline_init(mdev); - if (ret) - return ret; - - drm_mode_config_reset(dev); - - return 0; -} From 828369f2829e5415e61a2c25b2cfb0bad48d72b4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:41:02 +0200 Subject: [PATCH 235/396] drm/mgag200: Move CRTC atomic_enable to model-specific code The CRTC atomic_enable helper contains per-model branches for G200ER, G200EV and G200SE devices. Implement a dedicated helper for each of them and remove the branches from the shared helper. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-14-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.h | 6 +- drivers/gpu/drm/mgag200/mgag200_g200er.c | 50 ++++++++++++++- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 39 ++++++++++- drivers/gpu/drm/mgag200/mgag200_g200se.c | 80 ++++++++++++++++++++++- drivers/gpu/drm/mgag200/mgag200_mode.c | 82 +----------------------- 5 files changed, 172 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 1e7de8b12e75..26038fa3cf09 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -210,8 +210,6 @@ enum mga_type { G200_EW3, }; -#define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B) - struct mgag200_device_info { u16 max_hdisplay; u16 max_vdisplay; @@ -438,7 +436,9 @@ int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector); .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state -resource_size_t mgag200_device_probe_vram(struct mga_device *mdev); +void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode); +void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format); +void mgag200_enable_display(struct mga_device *mdev); void mgag200_init_registers(struct mga_device *mdev); int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 399f2443cb47..ae9bb38c1ac0 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -36,6 +36,22 @@ static void mgag200_g200er_init_registers(struct mga_device *mdev) WREG_ECRT(0x24, 0x5); /* G200ER specific */ } +static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev) +{ + static const uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */ + u32 memctl; + + memctl = RREG32(MGAREG_MEMCTL); + + memctl |= RESET_FLAG; + WREG32(MGAREG_MEMCTL, memctl); + + udelay(1000); + + memctl &= ~RESET_FLAG; + WREG32(MGAREG_MEMCTL, memctl); +} + /* * PIXPLLC */ @@ -164,8 +180,40 @@ static const struct drm_plane_funcs mgag200_g200er_primary_plane_funcs = { MGAG200_PRIMARY_PLANE_FUNCS, }; +static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + const struct mgag200_device_funcs *funcs = mdev->funcs; + struct drm_crtc_state *crtc_state = crtc->state; + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + const struct drm_format_info *format = mgag200_crtc_state->format; + + if (funcs->disable_vidrst) + funcs->disable_vidrst(mdev); + + mgag200_set_format_regs(mdev, format); + mgag200_set_mode_regs(mdev, adjusted_mode); + + if (funcs->pixpllc_atomic_update) + funcs->pixpllc_atomic_update(crtc, old_state); + + mgag200_g200er_reset_tagfifo(mdev); + + mgag200_enable_display(mdev); + + if (funcs->enable_vidrst) + funcs->enable_vidrst(mdev); +} + static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = { - MGAG200_CRTC_HELPER_FUNCS, + .mode_valid = mgag200_crtc_helper_mode_valid, + .atomic_check = mgag200_crtc_helper_atomic_check, + .atomic_flush = mgag200_crtc_helper_atomic_flush, + .atomic_enable = mgag200_g200er_crtc_helper_atomic_enable, + .atomic_disable = mgag200_crtc_helper_atomic_disable }; static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index 2165ec7d63e8..ec324d942b47 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -36,6 +36,11 @@ static void mgag200_g200ev_init_registers(struct mga_device *mdev) mgag200_init_registers(mdev); } +static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev) +{ + WREG_ECRT(0x06, 0x00); +} + /* * PIXPLLC */ @@ -176,8 +181,40 @@ static const struct drm_plane_funcs mgag200_g200ev_primary_plane_funcs = { MGAG200_PRIMARY_PLANE_FUNCS, }; +static void mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + const struct mgag200_device_funcs *funcs = mdev->funcs; + struct drm_crtc_state *crtc_state = crtc->state; + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + const struct drm_format_info *format = mgag200_crtc_state->format; + + if (funcs->disable_vidrst) + funcs->disable_vidrst(mdev); + + mgag200_set_format_regs(mdev, format); + mgag200_set_mode_regs(mdev, adjusted_mode); + + if (funcs->pixpllc_atomic_update) + funcs->pixpllc_atomic_update(crtc, old_state); + + mgag200_g200ev_set_hiprilvl(mdev); + + mgag200_enable_display(mdev); + + if (funcs->enable_vidrst) + funcs->enable_vidrst(mdev); +} + static const struct drm_crtc_helper_funcs mgag200_g200ev_crtc_helper_funcs = { - MGAG200_CRTC_HELPER_FUNCS, + .mode_valid = mgag200_crtc_helper_mode_valid, + .atomic_check = mgag200_crtc_helper_atomic_check, + .atomic_flush = mgag200_crtc_helper_atomic_flush, + .atomic_enable = mgag200_g200ev_crtc_helper_atomic_enable, + .atomic_disable = mgag200_crtc_helper_atomic_disable }; static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index a28f5203a95a..0addc3750413 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -61,6 +61,52 @@ static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se) mgag200_init_registers(mdev); } +static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, + const struct drm_display_mode *mode, + const struct drm_format_info *format) +{ + struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base); + unsigned int hiprilvl; + u8 crtcext6; + + if (g200se->unique_rev_id >= 0x04) { + hiprilvl = 0; + } else if (g200se->unique_rev_id >= 0x02) { + unsigned int bpp; + unsigned long mb; + + if (format->cpp[0] * 8 > 16) + bpp = 32; + else if (format->cpp[0] * 8 > 8) + bpp = 16; + else + bpp = 8; + + mb = (mode->clock * bpp) / 1000; + if (mb > 3100) + hiprilvl = 0; + else if (mb > 2600) + hiprilvl = 1; + else if (mb > 1900) + hiprilvl = 2; + else if (mb > 1160) + hiprilvl = 3; + else if (mb > 440) + hiprilvl = 4; + else + hiprilvl = 5; + + } else if (g200se->unique_rev_id >= 0x01) { + hiprilvl = 3; + } else { + hiprilvl = 4; + } + + crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */ + + WREG_ECRT(0x06, crtcext6); +} + /* * PIXPLLC */ @@ -265,8 +311,40 @@ static const struct drm_plane_funcs mgag200_g200se_primary_plane_funcs = { MGAG200_PRIMARY_PLANE_FUNCS, }; +static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = crtc->dev; + struct mga_device *mdev = to_mga_device(dev); + const struct mgag200_device_funcs *funcs = mdev->funcs; + struct drm_crtc_state *crtc_state = crtc->state; + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + const struct drm_format_info *format = mgag200_crtc_state->format; + + if (funcs->disable_vidrst) + funcs->disable_vidrst(mdev); + + mgag200_set_format_regs(mdev, format); + mgag200_set_mode_regs(mdev, adjusted_mode); + + if (funcs->pixpllc_atomic_update) + funcs->pixpllc_atomic_update(crtc, old_state); + + mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format); + + mgag200_enable_display(mdev); + + if (funcs->enable_vidrst) + funcs->enable_vidrst(mdev); +} + static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = { - MGAG200_CRTC_HELPER_FUNCS, + .mode_valid = mgag200_crtc_helper_mode_valid, + .atomic_check = mgag200_crtc_helper_atomic_check, + .atomic_flush = mgag200_crtc_helper_atomic_flush, + .atomic_enable = mgag200_g200se_crtc_helper_atomic_enable, + .atomic_disable = mgag200_crtc_helper_atomic_disable }; static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 789ea77b94ae..1f26d4716679 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -199,8 +199,7 @@ void mgag200_init_registers(struct mga_device *mdev) WREG8(MGA_MISC_OUT, misc); } -static void mgag200_set_mode_regs(struct mga_device *mdev, - const struct drm_display_mode *mode) +void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode) { const struct mgag200_device_info *info = mdev->info; unsigned int hdisplay, hsyncstart, hsyncend, htotal; @@ -324,7 +323,7 @@ static void mgag200_set_offset(struct mga_device *mdev, WREG_ECRT(0x00, crtcext0); } -static void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format) +void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format) { struct drm_device *dev = &mdev->base; unsigned int bpp, bppshift, scale; @@ -387,74 +386,7 @@ static void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_fo WREG_ECRT(3, crtcext3); } -static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev) -{ - static uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */ - u32 memctl; - - memctl = RREG32(MGAREG_MEMCTL); - - memctl |= RESET_FLAG; - WREG32(MGAREG_MEMCTL, memctl); - - udelay(1000); - - memctl &= ~RESET_FLAG; - WREG32(MGAREG_MEMCTL, memctl); -} - -static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, - const struct drm_display_mode *mode, - const struct drm_format_info *format) -{ - struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base); - unsigned int hiprilvl; - u8 crtcext6; - - if (g200se->unique_rev_id >= 0x04) { - hiprilvl = 0; - } else if (g200se->unique_rev_id >= 0x02) { - unsigned int bpp; - unsigned long mb; - - if (format->cpp[0] * 8 > 16) - bpp = 32; - else if (format->cpp[0] * 8 > 8) - bpp = 16; - else - bpp = 8; - - mb = (mode->clock * bpp) / 1000; - if (mb > 3100) - hiprilvl = 0; - else if (mb > 2600) - hiprilvl = 1; - else if (mb > 1900) - hiprilvl = 2; - else if (mb > 1160) - hiprilvl = 3; - else if (mb > 440) - hiprilvl = 4; - else - hiprilvl = 5; - - } else if (g200se->unique_rev_id >= 0x01) { - hiprilvl = 3; - } else { - hiprilvl = 4; - } - - crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */ - - WREG_ECRT(0x06, crtcext6); -} - -static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev) -{ - WREG_ECRT(0x06, 0x00); -} - -static void mgag200_enable_display(struct mga_device *mdev) +void mgag200_enable_display(struct mga_device *mdev) { u8 seq0, crtcext1; @@ -709,14 +641,6 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ if (funcs->pixpllc_atomic_update) funcs->pixpllc_atomic_update(crtc, old_state); - if (mdev->type == G200_ER) - mgag200_g200er_reset_tagfifo(mdev); - - if (IS_G200_SE(mdev)) - mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format); - else if (mdev->type == G200_EV) - mgag200_g200ev_set_hiprilvl(mdev); - mgag200_enable_display(mdev); if (funcs->enable_vidrst) From d4a3e50ffd9084e3eafb318e95ca91b5895a6e62 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 28 Jul 2022 14:41:03 +0200 Subject: [PATCH 236/396] drm/mgag200: Remove type field from struct mga_device Each model's specific code is located in a separate file. The type field in struct mga_device is no unused. Remove it. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-15-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 17 +++++++------ drivers/gpu/drm/mgag200/mgag200_drv.h | 29 ++++++++++------------- drivers/gpu/drm/mgag200/mgag200_g200.c | 5 ++-- drivers/gpu/drm/mgag200/mgag200_g200eh.c | 5 ++-- drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 5 ++-- drivers/gpu/drm/mgag200/mgag200_g200er.c | 5 ++-- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 5 ++-- drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 5 ++-- drivers/gpu/drm/mgag200/mgag200_g200se.c | 2 +- drivers/gpu/drm/mgag200/mgag200_g200wb.c | 5 ++-- 10 files changed, 35 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index c20a59a2cd91..d1e5933a6471 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -161,7 +161,7 @@ int mgag200_device_preinit(struct mga_device *mdev) return 0; } -int mgag200_device_init(struct mga_device *mdev, enum mga_type type, +int mgag200_device_init(struct mga_device *mdev, const struct mgag200_device_info *info, const struct mgag200_device_funcs *funcs) { @@ -171,7 +171,6 @@ int mgag200_device_init(struct mga_device *mdev, enum mga_type type, mdev->info = info; mdev->funcs = funcs; - mdev->type = type; ret = drmm_mutex_init(dev, &mdev->rmmio_lock); if (ret) @@ -234,29 +233,29 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) switch (type) { case G200_PCI: case G200_AGP: - mdev = mgag200_g200_device_create(pdev, &mgag200_driver, type); + mdev = mgag200_g200_device_create(pdev, &mgag200_driver); break; case G200_SE_A: case G200_SE_B: mdev = mgag200_g200se_device_create(pdev, &mgag200_driver, type); break; case G200_WB: - mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver, type); + mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver); break; case G200_EV: - mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver, type); + mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver); break; case G200_EH: - mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver, type); + mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver); break; case G200_EH3: - mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver, type); + mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver); break; case G200_ER: - mdev = mgag200_g200er_device_create(pdev, &mgag200_driver, type); + mdev = mgag200_g200er_device_create(pdev, &mgag200_driver); break; case G200_EW3: - mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver, type); + mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver); break; default: dev_err(&pdev->dev, "Device type %d is unsupported\n", type); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 26038fa3cf09..f0c2349404b4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -292,8 +292,6 @@ struct mga_device { void __iomem *vram; resource_size_t vram_available; - enum mga_type type; - struct drm_plane primary_plane; struct drm_crtc crtc; struct drm_encoder encoder; @@ -337,31 +335,28 @@ int mgag200_init_pci_options(struct pci_dev *pdev, u32 option, u32 option2); resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size); resource_size_t mgag200_device_probe_vram(struct mga_device *mdev); int mgag200_device_preinit(struct mga_device *mdev); -int mgag200_device_init(struct mga_device *mdev, enum mga_type type, +int mgag200_device_init(struct mga_device *mdev, const struct mgag200_device_info *info, const struct mgag200_device_funcs *funcs); /* mgag200_<device type>.c */ -struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type); +struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv); struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, enum mga_type type); void mgag200_g200wb_init_registers(struct mga_device *mdev); void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state); -struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type); -struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type); +struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv); +struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv); void mgag200_g200eh_init_registers(struct mga_device *mdev); void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state); -struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type); -struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type); -struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type); -struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type); +struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, + const struct drm_driver *drv); +struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, + const struct drm_driver *drv); +struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, + const struct drm_driver *drv); +struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, + const struct drm_driver *drv); /* * mgag200_mode.c diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c index dffcfa83ae74..bf5d7fe525a3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c @@ -398,8 +398,7 @@ static const struct mgag200_device_funcs mgag200_g200_device_funcs = { .pixpllc_atomic_update = mgag200_g200_pixpllc_atomic_update, }; -struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type) +struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv) { struct mgag200_g200_device *g200; struct mga_device *mdev; @@ -425,7 +424,7 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct mgag200_g200_init_refclk(g200); - ret = mgag200_device_init(mdev, type, &mgag200_g200_device_info, + ret = mgag200_device_init(mdev, &mgag200_g200_device_info, &mgag200_g200_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c index 54568d1f603a..fad62453a91d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c @@ -274,8 +274,7 @@ static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = { .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, }; -struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type) +struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv) { struct mga_device *mdev; struct drm_device *dev; @@ -297,7 +296,7 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200eh_device_info, + ret = mgag200_device_init(mdev, &mgag200_g200eh_device_info, &mgag200_g200eh_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c index 3e2929fd6145..0f7d8112cd49 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c @@ -179,8 +179,7 @@ static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = { }; struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, - const struct drm_driver *drv, - enum mga_type type) + const struct drm_driver *drv) { struct mga_device *mdev; struct drm_device *dev; @@ -202,7 +201,7 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200eh3_device_info, + ret = mgag200_device_init(mdev, &mgag200_g200eh3_device_info, &mgag200_g200eh3_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index ae9bb38c1ac0..bce267e0f7de 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -312,8 +312,7 @@ static const struct mgag200_device_funcs mgag200_g200er_device_funcs = { .pixpllc_atomic_update = mgag200_g200er_pixpllc_atomic_update, }; -struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type) +struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv) { struct mga_device *mdev; struct drm_device *dev; @@ -331,7 +330,7 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200er_device_info, + ret = mgag200_device_init(mdev, &mgag200_g200er_device_info, &mgag200_g200er_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index ec324d942b47..ac957f42abe1 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -313,8 +313,7 @@ static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = { .pixpllc_atomic_update = mgag200_g200ev_pixpllc_atomic_update, }; -struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type) +struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv) { struct mga_device *mdev; struct drm_device *dev; @@ -336,7 +335,7 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200ev_device_info, + ret = mgag200_device_init(mdev, &mgag200_g200ev_device_info, &mgag200_g200ev_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index 25b7bce31e0b..170934414d7d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -199,8 +199,7 @@ static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev } struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, - const struct drm_driver *drv, - enum mga_type type) + const struct drm_driver *drv) { struct mga_device *mdev; struct drm_device *dev; @@ -222,7 +221,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200ew3_device_info, + ret = mgag200_device_init(mdev, &mgag200_g200ew3_device_info, &mgag200_g200ew3_device_funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index 0addc3750413..be389ed91cbd 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -535,7 +535,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru else funcs = &mgag200_g200se_00_device_funcs; - ret = mgag200_device_init(mdev, type, info, funcs); + ret = mgag200_device_init(mdev, info, funcs); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index 01d21b6a4ce9..9baa727ac6f9 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -323,8 +323,7 @@ static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = { .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, }; -struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, - enum mga_type type) +struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv) { struct mga_device *mdev; struct drm_device *dev; @@ -346,7 +345,7 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru if (ret) return ERR_PTR(ret); - ret = mgag200_device_init(mdev, type, &mgag200_g200wb_device_info, + ret = mgag200_device_init(mdev, &mgag200_g200wb_device_info, &mgag200_g200wb_device_funcs); if (ret) return ERR_PTR(ret); From 5e8bf00ea915a0f290bf5ee544b91aad5eaab4bc Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Tue, 2 Aug 2022 02:04:01 +0200 Subject: [PATCH 237/396] drm/fb: remove unused includes of drm_fb_cma_helper.h Quite a lot of drivers include the drm_fb_cma_helper.h header file without actually making use of it's provided API, hence remove those includes. Suggested-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Danilo Krummrich <dakr@redhat.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220802000405.949236-2-dakr@redhat.com --- drivers/gpu/drm/arm/hdlcd_drv.c | 1 - drivers/gpu/drm/arm/malidp_drv.c | 1 - drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 1 - drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 1 - drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c | 1 - drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 1 - drivers/gpu/drm/imx/imx-drm-core.c | 1 - drivers/gpu/drm/imx/ipuv3-crtc.c | 1 - drivers/gpu/drm/logicvc/logicvc_mode.c | 1 - drivers/gpu/drm/pl111/pl111_drv.c | 1 - drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 1 - drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 - drivers/gpu/drm/rcar-du/rcar_du_kms.c | 1 - drivers/gpu/drm/shmobile/shmob_drm_kms.c | 1 - drivers/gpu/drm/solomon/ssd130x.c | 1 - drivers/gpu/drm/sti/sti_drv.c | 1 - drivers/gpu/drm/sti/sti_plane.c | 1 - drivers/gpu/drm/stm/drv.c | 1 - drivers/gpu/drm/sun4i/sun4i_drv.c | 1 - drivers/gpu/drm/sun4i/sun8i_mixer.c | 1 - drivers/gpu/drm/tidss/tidss_crtc.c | 1 - drivers/gpu/drm/tidss/tidss_kms.c | 1 - drivers/gpu/drm/tidss/tidss_plane.c | 1 - drivers/gpu/drm/tve200/tve200_drv.c | 1 - drivers/gpu/drm/v3d/v3d_drv.c | 1 - drivers/gpu/drm/vc4/vc4_drv.c | 1 - 26 files changed, 26 deletions(-) diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 350ca4e4eaa6..b32168e3f9ae 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -26,7 +26,6 @@ #include <drm/drm_crtc.h> #include <drm/drm_debugfs.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index d5aef21426cf..fa6c1a4254dc 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -19,7 +19,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index 7780b72de9e8..54aa8af45829 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -16,7 +16,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 7a503bf08d0f..4baa4977e473 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -20,7 +20,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_modeset_helper.h> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c index d763f53f480c..5b47000738e4 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c @@ -6,7 +6,6 @@ */ #include <drm/drm_atomic_helper.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 2af51df6dca7..e8b0fe970969 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -19,7 +19,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 50fd7aac5198..e43345bd1346 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -16,7 +16,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index f7863d6dea80..d9f832f952c2 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -18,7 +18,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/logicvc/logicvc_mode.c b/drivers/gpu/drm/logicvc/logicvc_mode.c index 11940704f644..c59da7039dc1 100644 --- a/drivers/gpu/drm/logicvc/logicvc_mode.c +++ b/drivers/gpu/drm/logicvc/logicvc_mode.c @@ -10,7 +10,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 19a4324bd356..5b5f3573b619 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -48,7 +48,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 169ca0c8912f..ed887ebd2f6b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -17,7 +17,6 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 70d85610d720..110ec9538b44 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -20,7 +20,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_managed.h> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 761451ee5263..7fed5b0c65ce 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -11,7 +11,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/shmobile/shmob_drm_kms.c index 68d21be784aa..edb003537530 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_kms.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.c @@ -9,7 +9,6 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 77f80b0d3a5e..973ae2dfb2f8 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -21,7 +21,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_edid.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index d858209cf8de..c0fbdb8cf6eb 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -14,7 +14,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_debugfs.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c index c74b524663ab..0a55180be22b 100644 --- a/drivers/gpu/drm/sti/sti_plane.c +++ b/drivers/gpu/drm/sti/sti_plane.c @@ -9,7 +9,6 @@ #include <linux/types.h> #include <drm/drm_blend.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index c63945dc2260..bb269dad30f9 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -18,7 +18,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 6eb1aabdb161..382074ef1394 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -17,7 +17,6 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_module.h> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 4e9bd9cb6b36..b3d1c0940406 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -16,7 +16,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c index ad4ce9d06622..92d2c25bb0ff 100644 --- a/drivers/gpu/drm/tidss/tidss_crtc.c +++ b/drivers/gpu/drm/tidss/tidss_crtc.c @@ -8,7 +8,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c index 666e527a0acf..b61db8f279e9 100644 --- a/drivers/gpu/drm/tidss/tidss_kms.c +++ b/drivers/gpu/drm/tidss/tidss_kms.c @@ -10,7 +10,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c index 68a85a94ffcb..42d50ec5526d 100644 --- a/drivers/gpu/drm/tidss/tidss_plane.c +++ b/drivers/gpu/drm/tidss/tidss_plane.c @@ -11,7 +11,6 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_atomic_helper.h> #include "tidss_crtc.h" diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index 6d9d2921abf4..86ebfe626cd0 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -39,7 +39,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 8c7f910daa28..e8c975b81585 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -22,7 +22,6 @@ #include <linux/reset.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_managed.h> #include <uapi/drm/v3d_drm.h> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 89975bdd607e..d33baf2667dd 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -33,7 +33,6 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_vblank.h> From 6bcfe8eaeef01fb389e951e7c648b934dfd62f15 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Tue, 2 Aug 2022 02:04:02 +0200 Subject: [PATCH 238/396] drm/fb: rename FB CMA helpers to FB DMA helpers Rename "FB CMA" helpers to "FB DMA" helpers - considering the hierarchy of APIs (mm/cma -> dma -> fb dma) calling them "FB DMA" seems to be more applicable. Besides that, commit e57924d4ae80 ("drm/doc: Task to rename CMA helpers") requests to rename the CMA helpers and implies that people seem to be confused about the naming. In order to do this renaming the following script was used: ``` #!/bin/bash DIRS="drivers/gpu include/drm Documentation/gpu" REGEX_SYM_UPPER="[0-9A-Z_\-]" REGEX_SYM_LOWER="[0-9a-z_\-]" REGEX_GREP_UPPER="(${REGEX_SYM_UPPER}*)(FB)_CMA_(${REGEX_SYM_UPPER}*)" REGEX_GREP_LOWER="(${REGEX_SYM_LOWER}*)(fb)_cma_(${REGEX_SYM_LOWER}*)" REGEX_SED_UPPER="s/${REGEX_GREP_UPPER}/\1\2_DMA_\3/g" REGEX_SED_LOWER="s/${REGEX_GREP_LOWER}/\1\2_dma_\3/g" # Find all upper case 'CMA' symbols and replace them with 'DMA'. for ff in $(grep -REHl "${REGEX_GREP_UPPER}" $DIRS) do sed -i -E "$REGEX_SED_UPPER" $ff done # Find all lower case 'cma' symbols and replace them with 'dma'. for ff in $(grep -REHl "${REGEX_GREP_LOWER}" $DIRS) do sed -i -E "$REGEX_SED_LOWER" $ff done # Replace all occurrences of 'CMA' / 'cma' in comments and # documentation files with 'DMA' / 'dma'. for ff in $(grep -RiHl " cma " $DIRS) do sed -i -E "s/ cma / dma /g" $ff sed -i -E "s/ CMA / DMA /g" $ff done ``` Only a few more manual modifications were needed, e.g. reverting the following modifications in some DRM Kconfig files - select CMA if HAVE_DMA_CONTIGUOUS + select DMA if HAVE_DMA_CONTIGUOUS as well as manually picking the occurrences of 'CMA'/'cma' in comments and documentation which relate to "FB CMA", but not "GEM CMA". This patch is compile-time tested building a x86_64 kernel with `make allyesconfig && make drivers/gpu/drm`. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Danilo Krummrich <dakr@redhat.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> #drivers/gpu/drm/arm Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220802000405.949236-3-dakr@redhat.com --- Documentation/gpu/drm-kms-helpers.rst | 8 ++-- drivers/gpu/drm/Makefile | 2 +- .../arm/display/komeda/komeda_framebuffer.c | 4 +- drivers/gpu/drm/arm/hdlcd_crtc.c | 4 +- drivers/gpu/drm/arm/malidp_mw.c | 4 +- drivers/gpu/drm/arm/malidp_planes.c | 8 ++-- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 4 +- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 4 +- ...rm_fb_cma_helper.c => drm_fb_dma_helper.c} | 43 +++++++++++-------- drivers/gpu/drm/drm_format_helper.c | 4 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 4 +- .../gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 4 +- drivers/gpu/drm/imx/dcss/dcss-plane.c | 6 +-- drivers/gpu/drm/imx/ipuv3-plane.c | 8 ++-- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 6 +-- drivers/gpu/drm/ingenic/ingenic-ipu.c | 10 ++--- drivers/gpu/drm/kmb/kmb_plane.c | 8 ++-- drivers/gpu/drm/logicvc/Kconfig | 2 +- drivers/gpu/drm/logicvc/logicvc_layer.c | 6 +-- drivers/gpu/drm/mcde/mcde_display.c | 6 +-- drivers/gpu/drm/mcde/mcde_drv.c | 4 +- drivers/gpu/drm/meson/meson_overlay.c | 8 ++-- drivers/gpu/drm/meson/meson_plane.c | 4 +- drivers/gpu/drm/mxsfb/lcdif_kms.c | 6 +-- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 8 ++-- drivers/gpu/drm/pl111/pl111_display.c | 6 +-- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 4 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 +-- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 6 +-- drivers/gpu/drm/sprd/sprd_dpu.c | 4 +- drivers/gpu/drm/sti/sti_cursor.c | 6 +-- drivers/gpu/drm/sti/sti_gdp.c | 6 +-- drivers/gpu/drm/sti/sti_hqvdp.c | 6 +-- drivers/gpu/drm/stm/ltdc.c | 14 +++--- drivers/gpu/drm/sun4i/sun4i_backend.c | 4 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 8 ++-- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 4 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +- drivers/gpu/drm/tegra/fb.c | 2 +- drivers/gpu/drm/tidss/tidss_dispc.c | 6 +-- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +- drivers/gpu/drm/tiny/arcpgu.c | 4 +- drivers/gpu/drm/tiny/ili9225.c | 4 +- drivers/gpu/drm/tiny/repaper.c | 4 +- drivers/gpu/drm/tiny/st7586.c | 4 +- drivers/gpu/drm/tve200/tve200_display.c | 10 ++--- drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++-- drivers/gpu/drm/vc4/vc4_plane.c | 10 ++--- drivers/gpu/drm/vc4/vc4_txp.c | 4 +- drivers/gpu/drm/xlnx/zynqmp_disp.c | 4 +- ...rm_fb_cma_helper.h => drm_fb_dma_helper.h} | 10 ++--- 52 files changed, 168 insertions(+), 163 deletions(-) rename drivers/gpu/drm/{drm_fb_cma_helper.c => drm_fb_dma_helper.c} (70%) rename include/drm/{drm_fb_cma_helper.h => drm_fb_dma_helper.h} (56%) diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 2d473bc64c9f..dbc85fd7a971 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -122,13 +122,13 @@ format Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_format_helper.c :export: -Framebuffer CMA Helper Functions Reference +Framebuffer DMA Helper Functions Reference ========================================== -.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c - :doc: framebuffer cma helper functions +.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c + :doc: framebuffer dma helper functions -.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c :export: Framebuffer GEM Helper Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 25016dcab55e..1d6e4f672b59 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o drm_cma_helper-y := drm_gem_cma_helper.o -drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_cma_helper.o +drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o drm_shmem_helper-y := drm_gem_shmem_helper.o diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index 3c372d2deb0a..ea45da663dfb 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -5,7 +5,7 @@ * */ #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_gem.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -247,7 +247,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane) return -EINVAL; } - obj = drm_fb_cma_get_gem_obj(fb, plane); + obj = drm_fb_dma_get_gem_obj(fb, plane); offset = fb->offsets[plane]; if (!fb->modifier) { diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 636ef9447830..d3cf788c0fa9 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -18,7 +18,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -273,7 +273,7 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, return; dest_h = drm_rect_height(&new_plane_state->dst); - scanout_start = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0); + scanout_start = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0); hdlcd = plane->dev->dev_private; hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index b66ca5b33a7f..7a9c900626ec 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -10,7 +10,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -160,7 +160,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, n_planes = fb->format->num_planes; for (i = 0; i < n_planes; i++) { - struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i); + struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, i); /* memory write buffers are never rotated */ u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0); diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index a1cee1a5b523..72e0162735fa 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -13,7 +13,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -722,19 +722,19 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, ptr = mp->layer->ptr + (plane_index << 4); /* - * drm_fb_cma_get_gem_addr() alters the physical base address of the + * drm_fb_dma_get_gem_addr() alters the physical base address of the * framebuffer as per the plane's src_x, src_y co-ordinates (ie to * take care of source cropping). * For AFBC, this is not needed as the cropping is handled by _AD_CROP_H * and _AD_CROP_V registers. */ if (!afbc) { - paddr = drm_fb_cma_get_gem_addr(fb, plane->state, + paddr = drm_fb_dma_get_gem_addr(fb, plane->state, plane_index); } else { struct drm_gem_cma_object *obj; - obj = drm_fb_cma_get_gem_obj(fb, plane_index); + obj = drm_fb_dma_get_gem_obj(fb, plane_index); if (WARN_ON(!obj)) return; diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index f3788d7d82d6..cc4d0fa6262c 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -7,7 +7,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -185,7 +185,7 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, if (!fb) return; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); if (!gem) return; writel(gem->paddr, priv->base + CRT_ADDR); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 10f31faf140c..ddcbfe7ea0c8 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -12,7 +12,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -448,7 +448,7 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); for (i = 0; i < state->nplanes; i++) { - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i); + struct drm_gem_cma_object *gem = drm_fb_dma_get_gem_obj(fb, i); state->dscrs[i]->addr = gem->paddr + state->offsets[i]; diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c similarity index 70% rename from drivers/gpu/drm/drm_fb_cma_helper.c rename to drivers/gpu/drm/drm_fb_dma_helper.c index 69c57273b184..85fd21cd9dda 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * drm kms/fb cma (contiguous memory allocator) helper functions + * drm kms/fb dma helper functions * * Copyright (C) 2012 Analog Devices Inc. * Author: Lars-Peter Clausen <lars@metafoo.de> @@ -10,7 +10,7 @@ */ #include <drm/drm_damage_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -20,17 +20,22 @@ #include <linux/module.h> /** - * DOC: framebuffer cma helper functions + * DOC: framebuffer dma helper functions * - * Provides helper functions for creating a cma (contiguous memory allocator) - * backed framebuffer. + * Provides helper functions for creating a DMA-contiguous framebuffer. + * + * Depending on the platform, the buffers may be physically non-contiguous and + * mapped through an IOMMU or a similar mechanism, or allocated from + * physically-contiguous memory (using, for instance, CMA or a pool of memory + * reserved at early boot). This is handled behind the scenes by the DMA mapping + * API. * * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create - * callback function to create a cma backed framebuffer. + * callback function to create a DMA-contiguous framebuffer. */ /** - * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer + * drm_fb_dma_get_gem_obj() - Get CMA GEM object for framebuffer * @fb: The framebuffer * @plane: Which plane * @@ -38,7 +43,7 @@ * * This function will usually be called from the CRTC callback functions. */ -struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, +struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane) { struct drm_gem_object *gem; @@ -49,20 +54,20 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, return to_drm_gem_cma_obj(gem); } -EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); +EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj); /** - * drm_fb_cma_get_gem_addr() - Get physical address for framebuffer, for pixel + * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for framebuffer, for pixel * formats where values are grouped in blocks this will get you the beginning of * the block * @fb: The framebuffer * @state: Which state of drm plane * @plane: Which plane - * Return the CMA GEM address for given framebuffer. + * Return the DMA GEM address for given framebuffer. * * This function will usually be called from the PLANE callback functions. */ -dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, +dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, struct drm_plane_state *state, unsigned int plane) { @@ -77,7 +82,7 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, u32 block_start_y; u32 num_hblocks; - obj = drm_fb_cma_get_gem_obj(fb, plane); + obj = drm_fb_dma_get_gem_obj(fb, plane); if (!obj) return 0; @@ -98,10 +103,10 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, return paddr; } -EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr); +EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr); /** - * drm_fb_cma_sync_non_coherent - Sync GEM object to non-coherent backing + * drm_fb_dma_sync_non_coherent - Sync GEM object to non-coherent backing * memory * @drm: DRM device * @old_state: Old plane state @@ -112,7 +117,7 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr); * in a plane's .atomic_update ensures that all the data in the backing * memory have been written to RAM. */ -void drm_fb_cma_sync_non_coherent(struct drm_device *drm, +void drm_fb_dma_sync_non_coherent(struct drm_device *drm, struct drm_plane_state *old_state, struct drm_plane_state *state) { @@ -125,11 +130,11 @@ void drm_fb_cma_sync_non_coherent(struct drm_device *drm, size_t nb_bytes; for (i = 0; i < finfo->num_planes; i++) { - cma_obj = drm_fb_cma_get_gem_obj(state->fb, i); + cma_obj = drm_fb_dma_get_gem_obj(state->fb, i); if (!cma_obj->map_noncoherent) continue; - daddr = drm_fb_cma_get_gem_addr(state->fb, state, i); + daddr = drm_fb_dma_get_gem_addr(state->fb, state, i); drm_atomic_helper_damage_iter_init(&iter, old_state, state); drm_atomic_for_each_plane_damage(&iter, &clip) { @@ -142,4 +147,4 @@ void drm_fb_cma_sync_non_coherent(struct drm_device *drm, } } } -EXPORT_SYMBOL_GPL(drm_fb_cma_sync_non_coherent); +EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent); diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index c6182b5de78b..400b16d9147d 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -54,7 +54,7 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix const void *sbuf; /* - * Some source buffers, such as CMA memory, use write-combine + * Some source buffers, such as DMA memory, use write-combine * caching, so reads are uncached. Speed up access by fetching * one line at a time. */ @@ -676,7 +676,7 @@ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vadd dst_pitch = DIV_ROUND_UP(linepixels, 8); /* - * The cma memory is write-combined so reads are uncached. + * The dma memory is write-combined so reads are uncached. * Speed up by fetching one line at a time. * * Also, format conversion from XR24 to monochrome are done diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index 3b20e79158c8..aba2b714e8a6 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -10,7 +10,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -95,7 +95,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, if (index < 0) return; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); switch (fb->format->format) { case DRM_FORMAT_RGB565: diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 2c7059b775a1..c5d304826c3b 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -24,7 +24,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -548,7 +548,7 @@ static const struct drm_crtc_funcs ade_crtc_funcs = { static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, u32 ch, u32 y, u32 in_h, u32 fmt) { - struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, 0); u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; u32 stride = fb->pitches[0]; u32 addr = (u32)obj->paddr + y * stride; diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c index c29f343f33e5..a333c13c9ebc 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-plane.c +++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c @@ -6,7 +6,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -156,7 +156,7 @@ static int dcss_plane_atomic_check(struct drm_plane *plane, if (!fb || !new_plane_state->crtc) return 0; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); WARN_ON(!cma_obj); crtc_state = drm_atomic_get_existing_crtc_state(state, @@ -218,7 +218,7 @@ static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) struct dcss_dev *dcss = plane->dev->dev_private; struct drm_framebuffer *fb = state->fb; const struct drm_format_info *format = fb->format; - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); unsigned long p1_ba = 0, p2_ba = 0; if (!format->is_yuv || diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index f1b397693af8..27bd16418002 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -8,7 +8,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -129,7 +129,7 @@ drm_plane_state_to_eba(struct drm_plane_state *state, int plane) int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_cma_get_gem_obj(fb, plane); + cma_obj = drm_fb_dma_get_gem_obj(fb, plane); BUG_ON(!cma_obj); return cma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y + @@ -145,7 +145,7 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_cma_get_gem_obj(fb, 1); + cma_obj = drm_fb_dma_get_gem_obj(fb, 1); BUG_ON(!cma_obj); x /= fb->format->hsub; @@ -164,7 +164,7 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_cma_get_gem_obj(fb, 2); + cma_obj = drm_fb_dma_get_gem_obj(fb, 2); BUG_ON(!cma_obj); x /= fb->format->hsub; diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index f5835e6bf877..1dd78145b4b9 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -31,7 +31,7 @@ #include <drm/drm_drv.h> #include <drm/drm_encoder.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -669,12 +669,12 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, if (newstate && newstate->fb) { if (priv->soc_info->map_noncoherent) - drm_fb_cma_sync_non_coherent(&priv->drm, oldstate, newstate); + drm_fb_dma_sync_non_coherent(&priv->drm, oldstate, newstate); crtc_state = newstate->crtc->state; plane_id = !!(priv->soc_info->has_osd && plane != &priv->f0); - addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0); + addr = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0); width = newstate->src_w >> 16; height = newstate->src_h >> 16; cpp = newstate->fb->format->cpp[0]; diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index c117073fd61e..21052600cef4 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -22,7 +22,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -362,15 +362,15 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, } if (ingenic_drm_map_noncoherent(ipu->master)) - drm_fb_cma_sync_non_coherent(ipu->drm, oldstate, newstate); + drm_fb_dma_sync_non_coherent(ipu->drm, oldstate, newstate); /* New addresses will be committed in vblank handler... */ - ipu->addr_y = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0); + ipu->addr_y = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0); if (finfo->num_planes > 1) - ipu->addr_u = drm_fb_cma_get_gem_addr(newstate->fb, newstate, + ipu->addr_u = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 1); if (finfo->num_planes > 2) - ipu->addr_v = drm_fb_cma_get_gem_addr(newstate->fb, newstate, + ipu->addr_v = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 2); if (!needs_modeset) diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c index e385b8741776..ca3246e48e45 100644 --- a/drivers/gpu/drm/kmb/kmb_plane.c +++ b/drivers/gpu/drm/kmb/kmb_plane.c @@ -8,7 +8,7 @@ #include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -403,7 +403,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id), (width * fb->format->cpp[0])); - addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0); + addr[Y_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0); kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id), addr[Y_PLANE] + fb->offsets[0]); val = get_pixel_format(fb->format->format); @@ -415,7 +415,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id), (width * fb->format->cpp[0])); - addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, + addr[U_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, U_PLANE); /* check if Cb/Cr is swapped*/ if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER)) @@ -436,7 +436,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id), ((width) * fb->format->cpp[0])); - addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb, + addr[V_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, V_PLANE); diff --git a/drivers/gpu/drm/logicvc/Kconfig b/drivers/gpu/drm/logicvc/Kconfig index 300b2be07385..73be27cc749c 100644 --- a/drivers/gpu/drm/logicvc/Kconfig +++ b/drivers/gpu/drm/logicvc/Kconfig @@ -3,7 +3,7 @@ config DRM_LOGICVC depends on DRM depends on OF || COMPILE_TEST select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_KMS_DMA_HELPER select DRM_GEM_CMA_HELPER help DRM display driver for the logiCVC programmable logic block from Xylon diff --git a/drivers/gpu/drm/logicvc/logicvc_layer.c b/drivers/gpu/drm/logicvc/logicvc_layer.c index 466f9bd88bc1..464000aea765 100644 --- a/drivers/gpu/drm/logicvc/logicvc_layer.c +++ b/drivers/gpu/drm/logicvc/logicvc_layer.c @@ -10,7 +10,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_plane.h> @@ -157,7 +157,7 @@ static void logicvc_plane_atomic_update(struct drm_plane *drm_plane, new_state->crtc_h - 1); if (logicvc->caps->layer_address) { - phys_addr_t fb_addr = drm_fb_cma_get_gem_addr(fb, new_state, 0); + phys_addr_t fb_addr = drm_fb_dma_get_gem_addr(fb, new_state, 0); regmap_write(logicvc->regmap, LOGICVC_LAYER_ADDRESS_REG(index), fb_addr); @@ -280,7 +280,7 @@ int logicvc_layer_buffer_find_setup(struct logicvc_drm *logicvc, return -ENOMEM; } - fb_addr = drm_fb_cma_get_gem_addr(fb, state, 0); + fb_addr = drm_fb_dma_get_gem_addr(fb, state, 0); if (fb_addr < logicvc->reserved_mem_base) { drm_err(drm_dev, "Framebuffer memory below reserved memory base!\n"); diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 4df477540d07..9247da47f0cf 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -11,7 +11,7 @@ #include <linux/media-bus-format.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -165,7 +165,7 @@ static int mcde_display_check(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = pstate->fb; if (fb) { - u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); /* FB base address must be dword aligned. */ if (offset & 3) { @@ -1424,7 +1424,7 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, * from the DRM core before the display is enabled. */ if (fb) { - mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0)); + mcde_set_extsrc(mcde, drm_fb_dma_get_gem_addr(fb, pstate, 0)); dev_info_once(mcde->dev, "first update of display contents\n"); /* * Usually the flow is already active, unless we are in diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index e601baa87e55..509c2b03bc42 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -37,7 +37,7 @@ * (effectively using channels 0..3) for concurrent use. * * In the current DRM/KMS setup, we use one external source, one overlay, - * one FIFO and one formatter which we connect to the simple CMA framebuffer + * one FIFO and one formatter which we connect to the simple DMA framebuffer * helpers. We then provide a bridge to the DSI port, and on the DSI port * bridge we connect hang a panel bridge or other bridge. This may be subject * to change as we exploit more of the hardware capabilities. @@ -68,7 +68,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> #include <drm/drm_gem_cma_helper.h> diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index 93c1cd2aab43..bfebf45d8402 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -11,7 +11,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -650,7 +650,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, switch (priv->viu.vd1_planes) { case 3: - gem = drm_fb_cma_get_gem_obj(fb, 2); + gem = drm_fb_dma_get_gem_obj(fb, 2); priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2]; priv->viu.vd1_stride2 = fb->pitches[2]; priv->viu.vd1_height2 = @@ -662,7 +662,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_height2); fallthrough; case 2: - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1]; priv->viu.vd1_stride1 = fb->pitches[1]; priv->viu.vd1_height1 = @@ -674,7 +674,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_height1); fallthrough; case 1: - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0]; priv->viu.vd1_stride0 = fb->pitches[0]; priv->viu.vd1_height0 = diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index f3d49e81acf4..51479715cce7 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -15,7 +15,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -365,7 +365,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane, } /* Update Canvas with buffer address */ - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); priv->viu.osd1_addr = gem->paddr; priv->viu.osd1_stride = fb->pitches[0]; diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index b27a54e31343..0df418774035 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -18,7 +18,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_encoder.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -296,7 +296,7 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc, lcdif_crtc_mode_set_nofb(lcdif, bridge_state, bus_format); /* Write cur_buf as well to avoid an initial corrupt frame */ - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) { writel(lower_32_bits(paddr), lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4); @@ -405,7 +405,7 @@ static void lcdif_plane_primary_atomic_update(struct drm_plane *plane, plane); dma_addr_t paddr; - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) { writel(lower_32_bits(paddr), lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 2da2be6c11f2..e55e9262afb2 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -20,7 +20,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_encoder.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -388,7 +388,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, mxsfb_crtc_mode_set_nofb(mxsfb, bridge_state, bus_format); /* Write cur_buf as well to avoid an initial corrupt frame */ - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) { writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf); writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); @@ -543,7 +543,7 @@ static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane, plane); dma_addr_t paddr; - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); } @@ -559,7 +559,7 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane, dma_addr_t paddr; u32 ctrl; - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (!paddr) { writel(0, mxsfb->base + LCDC_AS_CTRL); return; diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index 6263346f24c6..5f2429c3633e 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -15,7 +15,7 @@ #include <linux/media-bus-format.h> #include <linux/of_graph.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -94,7 +94,7 @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe, return -EINVAL; if (fb) { - u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); /* FB base address must be dword aligned. */ if (offset & 3) @@ -398,7 +398,7 @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = pstate->fb; if (fb) { - u32 addr = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0); writel(addr, priv->regs + CLCD_UBAS); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 07ba6bff5f5d..4ae444346991 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -12,7 +12,7 @@ #include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -350,7 +350,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp, pitch = fb->pitches[0] * 8 / state->format->bpp; for (i = 0; i < state->format->planes; ++i) { - gem = drm_fb_cma_get_gem_obj(fb, i); + gem = drm_fb_dma_get_gem_obj(fb, i); dma[i] = gem->paddr + fb->offsets[i]; } } else { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 5e985d46d68e..99d32f42e46d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -11,7 +11,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -183,7 +183,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, int ret; for (i = 0; i < fb->format->num_planes; ++i) { - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i); + struct drm_gem_cma_object *gem = drm_fb_dma_get_gem_obj(fb, i); struct sg_table *sgt = &sg_tables[i]; if (gem->sgt) { diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 387fbd2ab32d..94318f858ed6 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -12,7 +12,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -292,13 +292,13 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc, unsigned int bpp; bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); scrtc->dma[0] = gem->paddr + fb->offsets[0] + y * fb->pitches[0] + x * bpp / 8; if (scrtc->format->yuv) { bpp = scrtc->format->bpp - 8; - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); scrtc->dma[1] = gem->paddr + fb->offsets[1] + y / (bpp == 4 ? 2 : 1) * fb->pitches[1] + x * (bpp == 16 ? 2 : 1); diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 4763ea8e1af0..6fa64bce0c91 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -9,7 +9,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -45,13 +45,13 @@ static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane, unsigned int bpp; bpp = splane->format->yuv ? 8 : splane->format->bpp; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); splane->dma[0] = gem->paddr + fb->offsets[0] + y * fb->pitches[0] + x * bpp / 8; if (splane->format->yuv) { bpp = splane->format->bpp - 8; - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); splane->dma[1] = gem->paddr + fb->offsets[1] + y / (bpp == 4 ? 2 : 1) * fb->pitches[1] + x * (bpp == 16 ? 2 : 1); diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c index 10d21f7ab02d..5ea104e0beb8 100644 --- a/drivers/gpu/drm/sprd/sprd_dpu.c +++ b/drivers/gpu/drm/sprd/sprd_dpu.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -340,7 +340,7 @@ static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state) size = (src_w & 0xffff) | (src_h << 16); for (i = 0; i < fb->format->num_planes; i++) { - cma_obj = drm_fb_cma_get_gem_obj(fb, i); + cma_obj = drm_fb_dma_get_gem_obj(fb, i); addr = cma_obj->paddr + fb->offsets[i]; if (i == 0) diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index 1e9bd4241f10..d374fa50be60 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -11,7 +11,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -243,7 +243,7 @@ static int sti_cursor_atomic_check(struct drm_plane *drm_plane, } } - if (!drm_fb_cma_get_gem_obj(fb, 0)) { + if (!drm_fb_dma_get_gem_obj(fb, 0)) { DRM_ERROR("Can't get CMA GEM object for fb\n"); return -EINVAL; } @@ -278,7 +278,7 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane, dst_x = newstate->crtc_x; dst_y = newstate->crtc_y; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); /* Convert ARGB8888 to CLUT8 */ sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr); diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index af783f599306..623a09163f9f 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -12,7 +12,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -658,7 +658,7 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, return -EINVAL; } - if (!drm_fb_cma_get_gem_obj(fb, 0)) { + if (!drm_fb_dma_get_gem_obj(fb, 0)) { DRM_ERROR("Can't get CMA GEM object for fb\n"); return -EINVAL; } @@ -778,7 +778,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format); top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 271982080437..26284c5f5b22 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -16,7 +16,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -1055,7 +1055,7 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, return -EINVAL; } - if (!drm_fb_cma_get_gem_obj(fb, 0)) { + if (!drm_fb_dma_get_gem_obj(fb, 0)) { DRM_ERROR("Can't get CMA GEM object for fb\n"); return -EINVAL; } @@ -1178,7 +1178,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT; cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 8f3307b279e7..42a98ef73d03 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -28,7 +28,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_device.h> #include <drm/drm_edid.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -1346,7 +1346,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, } /* Sets the FB address */ - paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 0); + paddr = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 0); if (newstate->rotation & DRM_MODE_REFLECT_X) paddr += (fb->format->cpp[0] * (x1 - x0 + 1)) - 1; @@ -1380,7 +1380,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, case DRM_FORMAT_NV12: case DRM_FORMAT_NV21: /* Configure the auxiliary frame buffer address 0 */ - paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); + paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1); if (newstate->rotation & DRM_MODE_REFLECT_X) paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; @@ -1392,8 +1392,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, break; case DRM_FORMAT_YUV420: /* Configure the auxiliary frame buffer address 0 & 1 */ - paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); - paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); + paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1); + paddr2 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 2); if (newstate->rotation & DRM_MODE_REFLECT_X) { paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; @@ -1410,8 +1410,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, break; case DRM_FORMAT_YVU420: /* Configure the auxiliary frame buffer address 0 & 1 */ - paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); - paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); + paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 2); + paddr2 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1); if (newstate->rotation & DRM_MODE_REFLECT_X) { paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 0c69eab1fd37..fa4539c3b149 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -338,7 +338,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, fb->pitches[0] * 8); /* Get the start of the displayed memory */ - paddr = drm_fb_cma_get_gem_addr(fb, state, 0); + paddr = drm_fb_dma_get_gem_addr(fb, state, 0); DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); if (fb->format->is_yuv) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 462fae73eae9..4a811e803dac 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -14,7 +14,7 @@ #include <linux/reset.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -221,19 +221,19 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format); /* Set the physical address of the buffer in memory */ - paddr = drm_fb_cma_get_gem_addr(fb, state, 0); + paddr = drm_fb_dma_get_gem_addr(fb, state, 0); DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); if (fb->format->num_planes > 1) { - paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1); + paddr = drm_fb_dma_get_gem_addr(fb, state, swap ? 2 : 1); DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, paddr); } if (fb->format->num_planes > 2) { - paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2); + paddr = drm_fb_dma_get_gem_addr(fb, state, swap ? 1 : 2); DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG, paddr); diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 06ed571c37f0..900c71c47a3b 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -13,7 +13,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -200,7 +200,7 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel, ch_base = sun8i_channel_base(mixer, channel); /* Get the physical address of the buffer in memory */ - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index b9473efa308d..8b5dae30c8c5 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -7,7 +7,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -322,7 +322,7 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, for (i = 0; i < format->num_planes; i++) { /* Get the physical address of the buffer in memory */ - gem = drm_fb_cma_get_gem_obj(fb, i); + gem = drm_fb_dma_get_gem_obj(fb, i); DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index ed828de5ac01..9291209154a7 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -3,7 +3,7 @@ * Copyright (C) 2012-2013 Avionic Design GmbH * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. * - * Based on the KMS/FB CMA helpers + * Based on the KMS/FB DMA helpers * Copyright (C) 2012 Analog Devices Inc. */ diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index dd3c6a606ae2..cdd9a64f9736 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -24,7 +24,7 @@ #include <drm/drm_blend.h> #include <drm/drm_fourcc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_panel.h> @@ -1961,7 +1961,7 @@ dma_addr_t dispc_plane_state_paddr(const struct drm_plane_state *state) u32 x = state->src_x >> 16; u32 y = state->src_y >> 16; - gem = drm_fb_cma_get_gem_obj(state->fb, 0); + gem = drm_fb_dma_get_gem_obj(state->fb, 0); return gem->paddr + fb->offsets[0] + x * fb->format->cpp[0] + y * fb->pitches[0]; @@ -1978,7 +1978,7 @@ dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state) if (WARN_ON(state->fb->format->num_planes != 2)) return 0; - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); return gem->paddr + fb->offsets[1] + (x * fb->format->cpp[1] / fb->format->hsub) + diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 509fbae8c9a6..bd4f52242c0a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -12,7 +12,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_cma_helper.h> @@ -68,7 +68,7 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) dma_addr_t start, end; u64 dma_base_and_ceiling; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); start = gem->paddr + fb->offsets[0] + crtc->y * fb->pitches[0] + diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c index 7461cb401407..cdf320c547fb 100644 --- a/drivers/gpu/drm/tiny/arcpgu.c +++ b/drivers/gpu/drm/tiny/arcpgu.c @@ -11,7 +11,7 @@ #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_edid.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -226,7 +226,7 @@ static void arc_pgu_update(struct drm_simple_display_pipe *pipe, return; arcpgu = pipe_to_arcpgu_priv(pipe); - gem = drm_fb_cma_get_gem_obj(pipe->plane.state->fb, 0); + gem = drm_fb_dma_get_gem_obj(pipe->plane.state->fb, 0); arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr); } diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index 8d686eecd5f4..fc73ffa46a19 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -78,7 +78,7 @@ static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data) static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 013790c45d0a..6d3b5b3cb955 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -25,7 +25,7 @@ #include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> @@ -511,7 +511,7 @@ static void repaper_get_temperature(struct repaper_epd *epd) static int repaper_fb_dirty(struct drm_framebuffer *fb) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct repaper_epd *epd = drm_to_epd(fb->dev); struct drm_rect clip; int idx, ret = 0; diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 8eddb020c43e..b1584b362c79 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -15,7 +15,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> @@ -92,7 +92,7 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_rect *clip) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); void *src = cma_obj->vaddr; int ret = 0; diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index 771bad881714..6647aab8a25e 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -15,7 +15,7 @@ #include <linux/of_graph.h> #include <linux/delay.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -90,7 +90,7 @@ static int tve200_display_check(struct drm_simple_display_pipe *pipe, } if (fb) { - u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); /* FB base address must be dword aligned. */ if (offset & 3) { @@ -267,14 +267,14 @@ static void tve200_display_update(struct drm_simple_display_pipe *pipe, if (fb) { /* For RGB, the Y component is used as base address */ - writel(drm_fb_cma_get_gem_addr(fb, pstate, 0), + writel(drm_fb_dma_get_gem_addr(fb, pstate, 0), priv->regs + TVE200_Y_FRAME_BASE_ADDR); /* For three plane YUV we need two more addresses */ if (fb->format->format == DRM_FORMAT_YUV420) { - writel(drm_fb_cma_get_gem_addr(fb, pstate, 1), + writel(drm_fb_dma_get_gem_addr(fb, pstate, 1), priv->regs + TVE200_U_FRAME_BASE_ADDR); - writel(drm_fb_cma_get_gem_addr(fb, pstate, 2), + writel(drm_fb_dma_get_gem_addr(fb, pstate, 2), priv->regs + TVE200_V_FRAME_BASE_ADDR); } } diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index d3efa7e5b5ed..f85788401707 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -37,7 +37,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> @@ -824,7 +824,7 @@ static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) if (flip_state->old_fb) { struct drm_gem_cma_object *cma_bo = - drm_fb_cma_get_gem_obj(flip_state->old_fb, 0); + drm_fb_dma_get_gem_obj(flip_state->old_fb, 0); bo = to_vc4_bo(&cma_bo->base); } @@ -857,7 +857,7 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, struct vc4_async_flip_state *flip_state) { struct drm_framebuffer *fb = flip_state->fb; - struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_bo = drm_fb_dma_get_gem_obj(fb, 0); struct vc4_dev *vc4 = to_vc4_dev(dev); struct dma_fence *fence; int ret; @@ -945,7 +945,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_bo = drm_fb_dma_get_gem_obj(fb, 0); struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); int ret; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 243b29ab6f85..51e0e8aa2135 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_blend.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -339,7 +339,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); int num_planes = fb->format->num_planes; struct drm_crtc_state *crtc_state; u32 h_subsample = fb->format->hsub; @@ -1243,7 +1243,7 @@ u32 vc4_plane_dlist_size(const struct drm_plane_state *state) void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); uint32_t addr; /* We're skipping the address adjustment for negative origin, @@ -1387,7 +1387,7 @@ static int vc4_prepare_fb(struct drm_plane *plane, if (!state->fb) return 0; - bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); + bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); drm_gem_plane_helper_prepare_fb(plane, state); @@ -1405,7 +1405,7 @@ static void vc4_cleanup_fb(struct drm_plane *plane, if (plane->state->fb == state->fb || !state->fb) return; - bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); + bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); vc4_bo_dec_usecnt(bo); } diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 913e26dd62d4..af48ae68f213 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -17,7 +17,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_edid.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_panel.h> @@ -317,7 +317,7 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, if (!drm_dev_enter(drm, &idx)) return; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); TXP_WRITE(TXP_DST_PTR, gem->paddr + fb->offsets[0]); TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); TXP_WRITE(TXP_DIM, diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index a769422e3f1d..3bcb71c71db0 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -15,7 +15,7 @@ #include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_managed.h> @@ -1100,7 +1100,7 @@ static int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer, struct dma_async_tx_descriptor *desc; dma_addr_t paddr; - paddr = drm_fb_cma_get_gem_addr(state->fb, state, i); + paddr = drm_fb_dma_get_gem_addr(state->fb, state, i); dma->xt.numf = height; dma->sgl.size = width * info->cpp[i]; diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_dma_helper.h similarity index 56% rename from include/drm/drm_fb_cma_helper.h rename to include/drm/drm_fb_dma_helper.h index 6447e34528f8..05f657363b30 100644 --- a/include/drm/drm_fb_cma_helper.h +++ b/include/drm/drm_fb_dma_helper.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __DRM_FB_CMA_HELPER_H__ -#define __DRM_FB_CMA_HELPER_H__ +#ifndef __DRM_FB_DMA_HELPER_H__ +#define __DRM_FB_DMA_HELPER_H__ #include <linux/types.h> @@ -8,14 +8,14 @@ struct drm_device; struct drm_framebuffer; struct drm_plane_state; -struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, +struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane); -dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, +dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, struct drm_plane_state *state, unsigned int plane); -void drm_fb_cma_sync_non_coherent(struct drm_device *drm, +void drm_fb_dma_sync_non_coherent(struct drm_device *drm, struct drm_plane_state *old_state, struct drm_plane_state *state); From 4a83c26a1d8702c516db77fc4423ae896ee904f1 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Tue, 2 Aug 2022 02:04:03 +0200 Subject: [PATCH 239/396] drm/gem: rename GEM CMA helpers to GEM DMA helpers Rename "GEM CMA" helpers to "GEM DMA" helpers - considering the hierarchy of APIs (mm/cma -> dma -> gem dma) calling them "GEM DMA" seems to be more applicable. Besides that, commit e57924d4ae80 ("drm/doc: Task to rename CMA helpers") requests to rename the CMA helpers and implies that people seem to be confused about the naming. In order to do this renaming the following script was used: ``` #!/bin/bash DIRS="drivers/gpu include/drm Documentation/gpu" REGEX_SYM_UPPER="[0-9A-Z_\-]" REGEX_SYM_LOWER="[0-9a-z_\-]" REGEX_GREP_UPPER="(${REGEX_SYM_UPPER}*)(GEM)_CMA_(${REGEX_SYM_UPPER}*)" REGEX_GREP_LOWER="(${REGEX_SYM_LOWER}*)(gem)_cma_(${REGEX_SYM_LOWER}*)" REGEX_SED_UPPER="s/${REGEX_GREP_UPPER}/\1\2_DMA_\3/g" REGEX_SED_LOWER="s/${REGEX_GREP_LOWER}/\1\2_dma_\3/g" # Find all upper case 'CMA' symbols and replace them with 'DMA'. for ff in $(grep -REHl "${REGEX_GREP_UPPER}" $DIRS) do sed -i -E "$REGEX_SED_UPPER" $ff done # Find all lower case 'cma' symbols and replace them with 'dma'. for ff in $(grep -REHl "${REGEX_GREP_LOWER}" $DIRS) do sed -i -E "$REGEX_SED_LOWER" $ff done # Replace all occurrences of 'CMA' / 'cma' in comments and # documentation files with 'DMA' / 'dma'. for ff in $(grep -RiHl " cma " $DIRS) do sed -i -E "s/ cma / dma /g" $ff sed -i -E "s/ CMA / DMA /g" $ff done # Rename all 'cma_obj's to 'dma_obj'. for ff in $(grep -RiHl "cma_obj" $DIRS) do sed -i -E "s/cma_obj/dma_obj/g" $ff done ``` Only a few more manual modifications were needed, e.g. reverting the following modifications in some DRM Kconfig files - select CMA if HAVE_DMA_CONTIGUOUS + select DMA if HAVE_DMA_CONTIGUOUS as well as manually picking the occurrences of 'CMA'/'cma' in comments and documentation which relate to "GEM CMA", but not "FB CMA". Also drivers/gpu/drm/Makefile was fixed up manually after renaming drm_gem_cma_helper.c to drm_gem_dma_helper.c. This patch is compile-time tested building a x86_64 kernel with `make allyesconfig && make drivers/gpu/drm`. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Danilo Krummrich <dakr@redhat.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> #drivers/gpu/drm/arm Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220802000405.949236-4-dakr@redhat.com --- Documentation/gpu/drm-mm.rst | 16 +- drivers/gpu/drm/Kconfig | 4 +- drivers/gpu/drm/Makefile | 6 +- drivers/gpu/drm/arm/Kconfig | 4 +- drivers/gpu/drm/arm/display/Kconfig | 2 +- .../arm/display/komeda/komeda_framebuffer.c | 6 +- .../gpu/drm/arm/display/komeda/komeda_kms.c | 10 +- drivers/gpu/drm/arm/hdlcd_crtc.c | 2 +- drivers/gpu/drm/arm/hdlcd_drv.c | 6 +- drivers/gpu/drm/arm/malidp_drv.c | 8 +- drivers/gpu/drm/arm/malidp_mw.c | 4 +- drivers/gpu/drm/arm/malidp_planes.c | 16 +- drivers/gpu/drm/armada/armada_gem.c | 6 +- drivers/gpu/drm/aspeed/Kconfig | 2 +- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 4 +- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 6 +- drivers/gpu/drm/atmel-hlcdc/Kconfig | 2 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 6 +- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 4 +- drivers/gpu/drm/drm_fb_dma_helper.c | 20 +- drivers/gpu/drm/drm_file.c | 2 +- ..._gem_cma_helper.c => drm_gem_dma_helper.c} | 297 +++++++++--------- drivers/gpu/drm/drm_mipi_dbi.c | 2 +- drivers/gpu/drm/fsl-dcu/Kconfig | 2 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 6 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 4 +- drivers/gpu/drm/hisilicon/kirin/Kconfig | 2 +- .../gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 8 +- .../gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 2 +- drivers/gpu/drm/imx/Kconfig | 2 +- drivers/gpu/drm/imx/dcss/Kconfig | 2 +- drivers/gpu/drm/imx/dcss/dcss-kms.c | 6 +- drivers/gpu/drm/imx/dcss/dcss-plane.c | 16 +- drivers/gpu/drm/imx/imx-drm-core.c | 8 +- drivers/gpu/drm/imx/imx-drm.h | 2 +- drivers/gpu/drm/imx/ipuv3-crtc.c | 2 +- drivers/gpu/drm/imx/ipuv3-plane.c | 26 +- drivers/gpu/drm/ingenic/Kconfig | 2 +- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 8 +- drivers/gpu/drm/ingenic/ingenic-ipu.c | 2 +- drivers/gpu/drm/kmb/Kconfig | 2 +- drivers/gpu/drm/kmb/kmb_drv.c | 6 +- drivers/gpu/drm/kmb/kmb_plane.c | 2 +- drivers/gpu/drm/logicvc/Kconfig | 2 +- drivers/gpu/drm/logicvc/logicvc_crtc.c | 2 +- drivers/gpu/drm/logicvc/logicvc_drm.c | 10 +- drivers/gpu/drm/logicvc/logicvc_interface.c | 2 +- drivers/gpu/drm/logicvc/logicvc_mode.c | 2 +- drivers/gpu/drm/mcde/Kconfig | 2 +- drivers/gpu/drm/mcde/mcde_display.c | 2 +- drivers/gpu/drm/mcde/mcde_drv.c | 6 +- drivers/gpu/drm/mediatek/Kconfig | 2 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +- drivers/gpu/drm/mediatek/mtk_drm_gem.c | 4 +- drivers/gpu/drm/meson/Kconfig | 2 +- drivers/gpu/drm/meson/meson_drv.c | 10 +- drivers/gpu/drm/meson/meson_overlay.c | 4 +- drivers/gpu/drm/meson/meson_plane.c | 4 +- drivers/gpu/drm/msm/msm_drv.c | 2 +- drivers/gpu/drm/mxsfb/Kconfig | 4 +- drivers/gpu/drm/mxsfb/lcdif_drv.c | 6 +- drivers/gpu/drm/mxsfb/lcdif_kms.c | 2 +- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 6 +- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 2 +- drivers/gpu/drm/panel/Kconfig | 2 +- drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 6 +- drivers/gpu/drm/pl111/Kconfig | 2 +- drivers/gpu/drm/pl111/pl111_display.c | 2 +- drivers/gpu/drm/pl111/pl111_drv.c | 8 +- drivers/gpu/drm/rcar-du/Kconfig | 2 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 36 +-- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 4 +- drivers/gpu/drm/rockchip/Kconfig | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 4 +- drivers/gpu/drm/shmobile/Kconfig | 2 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 4 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 6 +- drivers/gpu/drm/shmobile/shmob_drm_kms.c | 2 +- drivers/gpu/drm/shmobile/shmob_drm_kms.h | 2 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 4 +- drivers/gpu/drm/sprd/Kconfig | 2 +- drivers/gpu/drm/sprd/sprd_dpu.c | 8 +- drivers/gpu/drm/sprd/sprd_drm.c | 6 +- drivers/gpu/drm/sti/Kconfig | 2 +- drivers/gpu/drm/sti/sti_cursor.c | 10 +- drivers/gpu/drm/sti/sti_drv.c | 6 +- drivers/gpu/drm/sti/sti_gdp.c | 14 +- drivers/gpu/drm/sti/sti_hqvdp.c | 14 +- drivers/gpu/drm/sti/sti_plane.c | 2 +- drivers/gpu/drm/stm/Kconfig | 2 +- drivers/gpu/drm/stm/drv.c | 10 +- drivers/gpu/drm/stm/ltdc.c | 2 +- drivers/gpu/drm/sun4i/Kconfig | 2 +- drivers/gpu/drm/sun4i/sun4i_backend.c | 2 +- drivers/gpu/drm/sun4i/sun4i_drv.c | 8 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 2 +- drivers/gpu/drm/sun4i/sun8i_mixer.c | 2 +- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 4 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +- drivers/gpu/drm/tidss/Kconfig | 2 +- drivers/gpu/drm/tidss/tidss_crtc.c | 2 +- drivers/gpu/drm/tidss/tidss_dispc.c | 6 +- drivers/gpu/drm/tidss/tidss_drv.c | 6 +- drivers/gpu/drm/tilcdc/Kconfig | 2 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 +- drivers/gpu/drm/tiny/Kconfig | 22 +- drivers/gpu/drm/tiny/arcpgu.c | 8 +- drivers/gpu/drm/tiny/hx8357d.c | 6 +- drivers/gpu/drm/tiny/ili9163.c | 6 +- drivers/gpu/drm/tiny/ili9225.c | 10 +- drivers/gpu/drm/tiny/ili9341.c | 6 +- drivers/gpu/drm/tiny/ili9486.c | 6 +- drivers/gpu/drm/tiny/mi0283qt.c | 6 +- drivers/gpu/drm/tiny/panel-mipi-dbi.c | 6 +- drivers/gpu/drm/tiny/repaper.c | 10 +- drivers/gpu/drm/tiny/st7586.c | 10 +- drivers/gpu/drm/tiny/st7735r.c | 6 +- drivers/gpu/drm/tve200/Kconfig | 2 +- drivers/gpu/drm/tve200/tve200_display.c | 2 +- drivers/gpu/drm/tve200/tve200_drv.c | 6 +- drivers/gpu/drm/v3d/v3d_gem.c | 4 +- drivers/gpu/drm/vc4/Kconfig | 2 +- drivers/gpu/drm/vc4/vc4_bo.c | 44 +-- drivers/gpu/drm/vc4/vc4_crtc.c | 14 +- drivers/gpu/drm/vc4/vc4_drv.c | 6 +- drivers/gpu/drm/vc4/vc4_drv.h | 18 +- drivers/gpu/drm/vc4/vc4_gem.c | 4 +- drivers/gpu/drm/vc4/vc4_plane.c | 4 +- drivers/gpu/drm/vc4/vc4_render_cl.c | 24 +- drivers/gpu/drm/vc4/vc4_txp.c | 2 +- drivers/gpu/drm/vc4/vc4_v3d.c | 4 +- drivers/gpu/drm/vc4/vc4_validate.c | 16 +- drivers/gpu/drm/vc4/vc4_validate_shaders.c | 2 +- drivers/gpu/drm/xlnx/Kconfig | 2 +- drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 8 +- include/drm/drm_fb_dma_helper.h | 2 +- include/drm/drm_gem.h | 2 +- ..._gem_cma_helper.h => drm_gem_dma_helper.h} | 156 ++++----- 143 files changed, 638 insertions(+), 641 deletions(-) rename drivers/gpu/drm/{drm_gem_cma_helper.c => drm_gem_dma_helper.c} (62%) rename include/drm/{drm_gem_cma_helper.h => drm_gem_dma_helper.h} (53%) diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index f32ccce5722d..a79fd3549ff8 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -300,12 +300,12 @@ Drivers that want to map the GEM object upfront instead of handling page faults can implement their own mmap file operation handler. For platforms without MMU the GEM core provides a helper method -drm_gem_cma_get_unmapped_area(). The mmap() routines will call this to get a +drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a proposed address for the mapping. -To use drm_gem_cma_get_unmapped_area(), drivers must fill the struct +To use drm_gem_dma_get_unmapped_area(), drivers must fill the struct :c:type:`struct file_operations <file_operations>` get_unmapped_area field with -a pointer on drm_gem_cma_get_unmapped_area(). +a pointer on drm_gem_dma_get_unmapped_area(). More detailed information about get_unmapped_area can be found in Documentation/admin-guide/mm/nommu-mmap.rst @@ -355,16 +355,16 @@ GEM Function Reference .. kernel-doc:: drivers/gpu/drm/drm_gem.c :export: -GEM CMA Helper Functions Reference +GEM DMA Helper Functions Reference ---------------------------------- -.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c - :doc: cma helpers +.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c + :doc: dma helpers -.. kernel-doc:: include/drm/drm_gem_cma_helper.h +.. kernel-doc:: include/drm/drm_gem_dma_helper.h :internal: -.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c :export: GEM SHMEM Helper Function Reference diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 1c91e1e861a5..0b2ad7212ee6 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -200,11 +200,11 @@ config DRM_TTM_HELPER help Helpers for ttm-based gem objects -config DRM_GEM_CMA_HELPER +config DRM_GEM_DMA_HELPER tristate depends on DRM help - Choose this if you need the GEM CMA helper functions + Choose this if you need the GEM DMA helper functions config DRM_GEM_SHMEM_HELPER tristate diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 1d6e4f672b59..25d0ba310509 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -40,9 +40,9 @@ obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o -drm_cma_helper-y := drm_gem_cma_helper.o -drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o -obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o +drm_dma_helper-y := drm_gem_dma_helper.o +drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o +obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o drm_shmem_helper-y := drm_gem_shmem_helper.o obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig index 6e3f1d600541..c1b89274d2a4 100644 --- a/drivers/gpu/drm/arm/Kconfig +++ b/drivers/gpu/drm/arm/Kconfig @@ -6,7 +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 + select DRM_GEM_DMA_HELPER help Choose this option if you have an ARM High Definition Colour LCD controller. @@ -27,7 +27,7 @@ config DRM_MALI_DISPLAY depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST) depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help Choose this option if you want to compile the ARM Mali Display diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig index e91598b60781..4acc4285a4eb 100644 --- a/drivers/gpu/drm/arm/display/Kconfig +++ b/drivers/gpu/drm/arm/display/Kconfig @@ -4,7 +4,7 @@ config DRM_KOMEDA depends on DRM && OF depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help Choose this option if you want to compile the ARM Komeda display diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index ea45da663dfb..f1b27db5dad5 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -7,7 +7,7 @@ #include <drm/drm_device.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_gem.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include "komeda_framebuffer.h" @@ -137,7 +137,7 @@ komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb, } min_size = komeda_fb_get_pixel_addr(kfb, 0, fb->height, i) - - to_drm_gem_cma_obj(obj)->paddr; + - to_drm_gem_dma_obj(obj)->paddr; if (obj->size < min_size) { DRM_DEBUG_KMS("The fb->obj[%d] size: 0x%zx lower than the minimum requirement: 0x%llx.\n", i, obj->size, min_size); @@ -239,7 +239,7 @@ dma_addr_t komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane) { struct drm_framebuffer *fb = &kfb->base; - const struct drm_gem_cma_object *obj; + const struct drm_gem_dma_object *obj; u32 offset, plane_x, plane_y, block_w, block_sz; if (plane >= fb->format->num_planes) { diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 327051bba5b6..451746ebbe71 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -11,7 +11,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> @@ -21,9 +21,9 @@ #include "komeda_framebuffer.h" #include "komeda_kms.h" -DEFINE_DRM_GEM_CMA_FOPS(komeda_cma_fops); +DEFINE_DRM_GEM_DMA_FOPS(komeda_cma_fops); -static int komeda_gem_cma_dumb_create(struct drm_file *file, +static int komeda_gem_dma_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { @@ -32,7 +32,7 @@ static int komeda_gem_cma_dumb_create(struct drm_file *file, args->pitch = ALIGN(pitch, mdev->chip.bus_width); - return drm_gem_cma_dumb_create_internal(file, dev, args); + return drm_gem_dma_dumb_create_internal(file, dev, args); } static irqreturn_t komeda_kms_irq_handler(int irq, void *data) @@ -60,7 +60,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data) static const struct drm_driver komeda_kms_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .lastclose = drm_fb_helper_lastclose, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_cma_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_dma_dumb_create), .fops = &komeda_cma_fops, .name = "komeda", .desc = "Arm Komeda Display Processor driver", diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index d3cf788c0fa9..7030339fa232 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -21,7 +21,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index b32168e3f9ae..a032003c340c 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -27,7 +27,7 @@ #include <drm/drm_debugfs.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_module.h> @@ -225,11 +225,11 @@ static void hdlcd_debugfs_init(struct drm_minor *minor) } #endif -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver hdlcd_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, #ifdef CONFIG_DEBUG_FS .debugfs_init = hdlcd_debugfs_init, #endif diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index fa6c1a4254dc..1d0b0c54ccc7 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -21,7 +21,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_module.h> @@ -456,7 +456,7 @@ static int malidp_irq_init(struct platform_device *pdev) return 0; } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static int malidp_dumb_create(struct drm_file *file_priv, struct drm_device *drm, @@ -468,7 +468,7 @@ static int malidp_dumb_create(struct drm_file *file_priv, args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment); - return drm_gem_cma_dumb_create_internal(file_priv, drm, args); + return drm_gem_dma_dumb_create_internal(file_priv, drm, args); } #ifdef CONFIG_DEBUG_FS @@ -565,7 +565,7 @@ static void malidp_debugfs_init(struct drm_minor *minor) static const struct drm_driver malidp_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create), #ifdef CONFIG_DEBUG_FS .debugfs_init = malidp_debugfs_init, #endif diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index 7a9c900626ec..cefae03f1bcc 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -13,7 +13,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_writeback.h> @@ -160,7 +160,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, n_planes = fb->format->num_planes; for (i = 0; i < n_planes; i++) { - struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, i); + struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, i); /* memory write buffers are never rotated */ u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0); diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 72e0162735fa..b7948ca0060c 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -16,7 +16,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_print.h> @@ -333,15 +333,15 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms, for (i = 0; i < ms->n_planes; i++) { struct drm_gem_object *obj; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct sg_table *sgt; struct scatterlist *sgl; obj = drm_gem_fb_get_obj(ms->base.fb, i); - cma_obj = to_drm_gem_cma_obj(obj); + dma_obj = to_drm_gem_dma_obj(obj); - if (cma_obj->sgt) - sgt = cma_obj->sgt; + if (dma_obj->sgt) + sgt = dma_obj->sgt; else sgt = obj->funcs->get_sg_table(obj); @@ -352,14 +352,14 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms, while (sgl) { if (sgl->length < pgsize) { - if (!cma_obj->sgt) + if (!dma_obj->sgt) kfree(sgt); return false; } sgl = sg_next(sgl); } - if (!cma_obj->sgt) + if (!dma_obj->sgt) kfree(sgt); } @@ -732,7 +732,7 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, paddr = drm_fb_dma_get_gem_addr(fb, plane->state, plane_index); } else { - struct drm_gem_cma_object *obj; + struct drm_gem_dma_object *obj; obj = drm_fb_dma_get_gem_obj(fb, plane_index); diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 147abf1a3968..5430265ad458 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -107,11 +107,11 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) } /* - * We could grab something from CMA if it's enabled, but that + * We could grab something from DMA if it's enabled, but that * involves building in a problem: * - * CMA's interface uses dma_alloc_coherent(), which provides us - * with an CPU virtual address and a device address. + * GEM DMA helper interface uses dma_alloc_coherent(), which provides + * us with an CPU virtual address and a device address. * * The CPU virtual address may be either an address in the kernel * direct mapped region (for example, as it would be on x86) or diff --git a/drivers/gpu/drm/aspeed/Kconfig b/drivers/gpu/drm/aspeed/Kconfig index 024ccab14f88..8137c39b057b 100644 --- a/drivers/gpu/drm/aspeed/Kconfig +++ b/drivers/gpu/drm/aspeed/Kconfig @@ -5,7 +5,7 @@ config DRM_ASPEED_GFX depends on (COMPILE_TEST || ARCH_ASPEED) depends on MMU select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DMA_CMA if HAVE_DMA_CONTIGUOUS select CMA if HAVE_DMA_CONTIGUOUS select MFD_SYSCON diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index cc4d0fa6262c..996b03bac87f 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -11,7 +11,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_panel.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> @@ -168,7 +168,7 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_crtc *crtc = &pipe->crtc; struct drm_framebuffer *fb = pipe->plane.state->fb; struct drm_pending_vblank_event *event; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; spin_lock_irq(&crtc->dev->event_lock); event = crtc->state->event; diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index 54aa8af45829..a94f1a9e8f40 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -17,7 +17,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_device.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> @@ -245,11 +245,11 @@ static void aspeed_gfx_unload(struct drm_device *drm) drm_kms_helper_poll_fini(drm); } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver aspeed_gfx_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fops, .name = "aspeed-gfx-drm", .desc = "ASPEED GFX DRM", diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig b/drivers/gpu/drm/atmel-hlcdc/Kconfig index 8ae679f1a518..3bdbab3a6333 100644 --- a/drivers/gpu/drm/atmel-hlcdc/Kconfig +++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig @@ -2,7 +2,7 @@ config DRM_ATMEL_HLCDC tristate "DRM Support for ATMEL HLCDC Display Controller" depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL help diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 651e3c109360..f7e7f4e919c7 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -20,7 +20,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> @@ -730,11 +730,11 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev) clk_disable_unprepare(dc->hlcdc->periph_clk); } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver atmel_hlcdc_dc_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fops, .name = "atmel-hlcdc", .desc = "Atmel HLCD Controller DRM", diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index ddcbfe7ea0c8..48481aa2731a 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -15,7 +15,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "atmel_hlcdc_dc.h" @@ -448,7 +448,7 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); for (i = 0; i < state->nplanes; i++) { - struct drm_gem_cma_object *gem = drm_fb_dma_get_gem_obj(fb, i); + struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); state->dscrs[i]->addr = gem->paddr + state->offsets[i]; diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c index 85fd21cd9dda..b601073c22de 100644 --- a/drivers/gpu/drm/drm_fb_dma_helper.c +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -13,7 +13,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane.h> #include <linux/dma-mapping.h> @@ -35,15 +35,15 @@ */ /** - * drm_fb_dma_get_gem_obj() - Get CMA GEM object for framebuffer + * drm_fb_dma_get_gem_obj() - Get DMA GEM object for framebuffer * @fb: The framebuffer * @plane: Which plane * - * Return the CMA GEM object for given framebuffer. + * Return the DMA GEM object for given framebuffer. * * This function will usually be called from the CRTC callback functions. */ -struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, +struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane) { struct drm_gem_object *gem; @@ -52,7 +52,7 @@ struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, if (!gem) return NULL; - return to_drm_gem_cma_obj(gem); + return to_drm_gem_dma_obj(gem); } EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj); @@ -71,7 +71,7 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, struct drm_plane_state *state, unsigned int plane) { - struct drm_gem_cma_object *obj; + struct drm_gem_dma_object *obj; dma_addr_t paddr; u8 h_div = 1, v_div = 1; u32 block_w = drm_format_info_block_width(fb->format, plane); @@ -113,7 +113,7 @@ EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr); * @state: New plane state * * This function can be used by drivers that use damage clips and have - * CMA GEM objects backed by non-coherent memory. Calling this function + * DMA GEM objects backed by non-coherent memory. Calling this function * in a plane's .atomic_update ensures that all the data in the backing * memory have been written to RAM. */ @@ -123,15 +123,15 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm, { const struct drm_format_info *finfo = state->fb->format; struct drm_atomic_helper_damage_iter iter; - const struct drm_gem_cma_object *cma_obj; + const struct drm_gem_dma_object *dma_obj; unsigned int offset, i; struct drm_rect clip; dma_addr_t daddr; size_t nb_bytes; for (i = 0; i < finfo->num_planes; i++) { - cma_obj = drm_fb_dma_get_gem_obj(state->fb, i); - if (!cma_obj->map_noncoherent) + dma_obj = drm_fb_dma_get_gem_obj(state->fb, i); + if (!dma_obj->map_noncoherent) continue; daddr = drm_fb_dma_get_gem_addr(state->fb, state, i); diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ed25168619fc..fa55c9a562f3 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -131,7 +131,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev) * }; * * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for - * CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this + * DMA based drivers there is the DEFINE_DRM_GEM_DMA_FOPS() macro to make this * simpler. * * The driver's &file_operations must be stored in &drm_driver.fops. diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c similarity index 62% rename from drivers/gpu/drm/drm_gem_cma_helper.c rename to drivers/gpu/drm/drm_gem_dma_helper.c index 42abee9a0f4f..f1780c01c928 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_dma_helper.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * drm gem CMA (contiguous memory allocator) helper functions + * drm gem DMA helper functions * * Copyright (C) 2012 Sascha Hauer, Pengutronix * @@ -20,20 +20,17 @@ #include <drm/drm.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_vma_manager.h> /** - * DOC: cma helpers + * DOC: dma helpers * - * The DRM GEM/CMA helpers are a means to provide buffer objects that are + * The DRM GEM/DMA helpers are a means to provide buffer objects that are * presented to the device as a contiguous chunk of memory. This is useful * for devices that do not support scatter-gather DMA (either directly or * by using an intimately attached IOMMU). * - * Despite the name, the DRM GEM/CMA helpers are not hardwired to use the - * Contiguous Memory Allocator (CMA). - * * For devices that access the memory bus through an (external) IOMMU then * the buffer objects are allocated using a traditional page-based * allocator and may be scattered through physical memory. However they @@ -44,36 +41,36 @@ * objects that are physically contiguous in memory. * * For GEM callback helpers in struct &drm_gem_object functions, see likewise - * named functions with an _object_ infix (e.g., drm_gem_cma_object_vmap() wraps - * drm_gem_cma_vmap()). These helpers perform the necessary type conversion. + * named functions with an _object_ infix (e.g., drm_gem_dma_object_vmap() wraps + * drm_gem_dma_vmap()). These helpers perform the necessary type conversion. */ -static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = { - .free = drm_gem_cma_object_free, - .print_info = drm_gem_cma_object_print_info, - .get_sg_table = drm_gem_cma_object_get_sg_table, - .vmap = drm_gem_cma_object_vmap, - .mmap = drm_gem_cma_object_mmap, - .vm_ops = &drm_gem_cma_vm_ops, +static const struct drm_gem_object_funcs drm_gem_dma_default_funcs = { + .free = drm_gem_dma_object_free, + .print_info = drm_gem_dma_object_print_info, + .get_sg_table = drm_gem_dma_object_get_sg_table, + .vmap = drm_gem_dma_object_vmap, + .mmap = drm_gem_dma_object_mmap, + .vm_ops = &drm_gem_dma_vm_ops, }; /** - * __drm_gem_cma_create - Create a GEM CMA object without allocating memory + * __drm_gem_dma_create - Create a GEM DMA object without allocating memory * @drm: DRM device * @size: size of the object to allocate * @private: true if used for internal purposes * - * This function creates and initializes a GEM CMA object of the given size, + * This function creates and initializes a GEM DMA object of the given size, * but doesn't allocate any memory to back the object. * * Returns: - * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative + * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative * error code on failure. */ -static struct drm_gem_cma_object * -__drm_gem_cma_create(struct drm_device *drm, size_t size, bool private) +static struct drm_gem_dma_object * +__drm_gem_dma_create(struct drm_device *drm, size_t size, bool private) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_gem_object *gem_obj; int ret = 0; @@ -81,22 +78,22 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size, bool private) gem_obj = drm->driver->gem_create_object(drm, size); if (IS_ERR(gem_obj)) return ERR_CAST(gem_obj); - cma_obj = to_drm_gem_cma_obj(gem_obj); + dma_obj = to_drm_gem_dma_obj(gem_obj); } else { - cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); - if (!cma_obj) + dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL); + if (!dma_obj) return ERR_PTR(-ENOMEM); - gem_obj = &cma_obj->base; + gem_obj = &dma_obj->base; } if (!gem_obj->funcs) - gem_obj->funcs = &drm_gem_cma_default_funcs; + gem_obj->funcs = &drm_gem_dma_default_funcs; if (private) { drm_gem_private_object_init(drm, gem_obj, size); /* Always use writecombine for dma-buf mappings */ - cma_obj->map_noncoherent = false; + dma_obj->map_noncoherent = false; } else { ret = drm_gem_object_init(drm, gem_obj, size); } @@ -109,19 +106,19 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size, bool private) goto error; } - return cma_obj; + return dma_obj; error: - kfree(cma_obj); + kfree(dma_obj); return ERR_PTR(ret); } /** - * drm_gem_cma_create - allocate an object with the given size + * drm_gem_dma_create - allocate an object with the given size * @drm: DRM device * @size: size of the object to allocate * - * This function creates a CMA GEM object and allocates memory as backing store. + * This function creates a DMA GEM object and allocates memory as backing store. * The allocated memory will occupy a contiguous chunk of bus address space. * * For devices that are directly connected to the memory bus then the allocated @@ -131,78 +128,78 @@ error: * requirements. * * Returns: - * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative + * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative * error code on failure. */ -struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, +struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm, size_t size) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; int ret; size = round_up(size, PAGE_SIZE); - cma_obj = __drm_gem_cma_create(drm, size, false); - if (IS_ERR(cma_obj)) - return cma_obj; + dma_obj = __drm_gem_dma_create(drm, size, false); + if (IS_ERR(dma_obj)) + return dma_obj; - if (cma_obj->map_noncoherent) { - cma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size, - &cma_obj->paddr, + if (dma_obj->map_noncoherent) { + dma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size, + &dma_obj->paddr, DMA_TO_DEVICE, GFP_KERNEL | __GFP_NOWARN); } else { - cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr, + dma_obj->vaddr = dma_alloc_wc(drm->dev, size, &dma_obj->paddr, GFP_KERNEL | __GFP_NOWARN); } - if (!cma_obj->vaddr) { + if (!dma_obj->vaddr) { drm_dbg(drm, "failed to allocate buffer with size %zu\n", size); ret = -ENOMEM; goto error; } - return cma_obj; + return dma_obj; error: - drm_gem_object_put(&cma_obj->base); + drm_gem_object_put(&dma_obj->base); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(drm_gem_cma_create); +EXPORT_SYMBOL_GPL(drm_gem_dma_create); /** - * drm_gem_cma_create_with_handle - allocate an object with the given size and + * drm_gem_dma_create_with_handle - allocate an object with the given size and * return a GEM handle to it * @file_priv: DRM file-private structure to register the handle for * @drm: DRM device * @size: size of the object to allocate * @handle: return location for the GEM handle * - * This function creates a CMA GEM object, allocating a chunk of memory as + * This function creates a DMA GEM object, allocating a chunk of memory as * backing store. The GEM object is then added to the list of object associated * with the given file and a handle to it is returned. * * The allocated memory will occupy a contiguous chunk of bus address space. - * See drm_gem_cma_create() for more details. + * See drm_gem_dma_create() for more details. * * Returns: - * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative + * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative * error code on failure. */ -static struct drm_gem_cma_object * -drm_gem_cma_create_with_handle(struct drm_file *file_priv, +static struct drm_gem_dma_object * +drm_gem_dma_create_with_handle(struct drm_file *file_priv, struct drm_device *drm, size_t size, uint32_t *handle) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_gem_object *gem_obj; int ret; - cma_obj = drm_gem_cma_create(drm, size); - if (IS_ERR(cma_obj)) - return cma_obj; + dma_obj = drm_gem_dma_create(drm, size); + if (IS_ERR(dma_obj)) + return dma_obj; - gem_obj = &cma_obj->base; + gem_obj = &dma_obj->base; /* * allocate a id of idr table where the obj is registered @@ -214,44 +211,44 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, if (ret) return ERR_PTR(ret); - return cma_obj; + return dma_obj; } /** - * drm_gem_cma_free - free resources associated with a CMA GEM object - * @cma_obj: CMA GEM object to free + * drm_gem_dma_free - free resources associated with a DMA GEM object + * @dma_obj: DMA GEM object to free * - * This function frees the backing memory of the CMA GEM object, cleans up the + * This function frees the backing memory of the DMA GEM object, cleans up the * GEM object state and frees the memory used to store the object itself. * If the buffer is imported and the virtual address is set, it is released. */ -void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj) +void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj) { - struct drm_gem_object *gem_obj = &cma_obj->base; - struct iosys_map map = IOSYS_MAP_INIT_VADDR(cma_obj->vaddr); + struct drm_gem_object *gem_obj = &dma_obj->base; + struct iosys_map map = IOSYS_MAP_INIT_VADDR(dma_obj->vaddr); if (gem_obj->import_attach) { - if (cma_obj->vaddr) + if (dma_obj->vaddr) dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map); - drm_prime_gem_destroy(gem_obj, cma_obj->sgt); - } else if (cma_obj->vaddr) { - if (cma_obj->map_noncoherent) - dma_free_noncoherent(gem_obj->dev->dev, cma_obj->base.size, - cma_obj->vaddr, cma_obj->paddr, + drm_prime_gem_destroy(gem_obj, dma_obj->sgt); + } else if (dma_obj->vaddr) { + if (dma_obj->map_noncoherent) + dma_free_noncoherent(gem_obj->dev->dev, dma_obj->base.size, + dma_obj->vaddr, dma_obj->paddr, DMA_TO_DEVICE); else - dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, - cma_obj->vaddr, cma_obj->paddr); + dma_free_wc(gem_obj->dev->dev, dma_obj->base.size, + dma_obj->vaddr, dma_obj->paddr); } drm_gem_object_release(gem_obj); - kfree(cma_obj); + kfree(dma_obj); } -EXPORT_SYMBOL_GPL(drm_gem_cma_free); +EXPORT_SYMBOL_GPL(drm_gem_dma_free); /** - * drm_gem_cma_dumb_create_internal - create a dumb buffer object + * drm_gem_dma_dumb_create_internal - create a dumb buffer object * @file_priv: DRM file-private structure to create the dumb buffer for * @drm: DRM device * @args: IOCTL data @@ -264,12 +261,12 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_free); * Returns: * 0 on success or a negative error code on failure. */ -int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv, +int drm_gem_dma_dumb_create_internal(struct drm_file *file_priv, struct drm_device *drm, struct drm_mode_create_dumb *args) { unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; if (args->pitch < min_pitch) args->pitch = min_pitch; @@ -277,14 +274,14 @@ int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv, if (args->size < args->pitch * args->height) args->size = args->pitch * args->height; - cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size, + dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size, &args->handle); - return PTR_ERR_OR_ZERO(cma_obj); + return PTR_ERR_OR_ZERO(dma_obj); } -EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_internal); +EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create_internal); /** - * drm_gem_cma_dumb_create - create a dumb buffer object + * drm_gem_dma_dumb_create - create a dumb buffer object * @file_priv: DRM file-private structure to create the dumb buffer for * @drm: DRM device * @args: IOCTL data @@ -296,35 +293,35 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_internal); * * For hardware with additional restrictions, drivers can adjust the fields * set up by userspace and pass the IOCTL data along to the - * drm_gem_cma_dumb_create_internal() function. + * drm_gem_dma_dumb_create_internal() function. * * Returns: * 0 on success or a negative error code on failure. */ -int drm_gem_cma_dumb_create(struct drm_file *file_priv, +int drm_gem_dma_dumb_create(struct drm_file *file_priv, struct drm_device *drm, struct drm_mode_create_dumb *args) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); args->size = args->pitch * args->height; - cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size, + dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size, &args->handle); - return PTR_ERR_OR_ZERO(cma_obj); + return PTR_ERR_OR_ZERO(dma_obj); } -EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create); +EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create); -const struct vm_operations_struct drm_gem_cma_vm_ops = { +const struct vm_operations_struct drm_gem_dma_vm_ops = { .open = drm_gem_vm_open, .close = drm_gem_vm_close, }; -EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops); +EXPORT_SYMBOL_GPL(drm_gem_dma_vm_ops); #ifndef CONFIG_MMU /** - * drm_gem_cma_get_unmapped_area - propose address for mapping in noMMU cases + * drm_gem_dma_get_unmapped_area - propose address for mapping in noMMU cases * @filp: file object * @addr: memory address * @len: buffer size @@ -339,13 +336,13 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops); * Returns: * mapping address on success or a negative error code on failure. */ -unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, +unsigned long drm_gem_dma_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_gem_object *obj = NULL; struct drm_file *priv = filp->private_data; struct drm_device *dev = priv->minor->dev; @@ -384,35 +381,35 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, return -EACCES; } - cma_obj = to_drm_gem_cma_obj(obj); + dma_obj = to_drm_gem_dma_obj(obj); drm_gem_object_put(obj); - return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL; + return dma_obj->vaddr ? (unsigned long)dma_obj->vaddr : -EINVAL; } -EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area); +EXPORT_SYMBOL_GPL(drm_gem_dma_get_unmapped_area); #endif /** - * drm_gem_cma_print_info() - Print &drm_gem_cma_object info for debugfs - * @cma_obj: CMA GEM object + * drm_gem_dma_print_info() - Print &drm_gem_dma_object info for debugfs + * @dma_obj: DMA GEM object * @p: DRM printer * @indent: Tab indentation level * * This function prints paddr and vaddr for use in e.g. debugfs output. */ -void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj, +void drm_gem_dma_print_info(const struct drm_gem_dma_object *dma_obj, struct drm_printer *p, unsigned int indent) { - drm_printf_indent(p, indent, "paddr=%pad\n", &cma_obj->paddr); - drm_printf_indent(p, indent, "vaddr=%p\n", cma_obj->vaddr); + drm_printf_indent(p, indent, "paddr=%pad\n", &dma_obj->paddr); + drm_printf_indent(p, indent, "vaddr=%p\n", dma_obj->vaddr); } -EXPORT_SYMBOL(drm_gem_cma_print_info); +EXPORT_SYMBOL(drm_gem_dma_print_info); /** - * drm_gem_cma_get_sg_table - provide a scatter/gather table of pinned - * pages for a CMA GEM object - * @cma_obj: CMA GEM object + * drm_gem_dma_get_sg_table - provide a scatter/gather table of pinned + * pages for a DMA GEM object + * @dma_obj: DMA GEM object * * This function exports a scatter/gather table by calling the standard * DMA mapping API. @@ -420,9 +417,9 @@ EXPORT_SYMBOL(drm_gem_cma_print_info); * Returns: * A pointer to the scatter/gather table of pinned pages or NULL on failure. */ -struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj) +struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj) { - struct drm_gem_object *obj = &cma_obj->base; + struct drm_gem_object *obj = &dma_obj->base; struct sg_table *sgt; int ret; @@ -430,8 +427,8 @@ struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj) if (!sgt) return ERR_PTR(-ENOMEM); - ret = dma_get_sgtable(obj->dev->dev, sgt, cma_obj->vaddr, - cma_obj->paddr, obj->size); + ret = dma_get_sgtable(obj->dev->dev, sgt, dma_obj->vaddr, + dma_obj->paddr, obj->size); if (ret < 0) goto out; @@ -441,10 +438,10 @@ out: kfree(sgt); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table); +EXPORT_SYMBOL_GPL(drm_gem_dma_get_sg_table); /** - * drm_gem_cma_prime_import_sg_table - produce a CMA GEM object from another + * drm_gem_dma_prime_import_sg_table - produce a DMA GEM object from another * driver's scatter/gather table of pinned pages * @dev: device to import into * @attach: DMA-BUF attachment @@ -453,7 +450,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table); * This function imports a scatter/gather table exported via DMA-BUF by * another driver. Imported buffers must be physically contiguous in memory * (i.e. the scatter/gather table must contain a single entry). Drivers that - * use the CMA helpers should set this as their + * use the DMA helpers should set this as their * &drm_driver.gem_prime_import_sg_table callback. * * Returns: @@ -461,56 +458,56 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table); * error code on failure. */ struct drm_gem_object * -drm_gem_cma_prime_import_sg_table(struct drm_device *dev, +drm_gem_dma_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; /* check if the entries in the sg_table are contiguous */ if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) return ERR_PTR(-EINVAL); - /* Create a CMA GEM buffer. */ - cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size, true); - if (IS_ERR(cma_obj)) - return ERR_CAST(cma_obj); + /* Create a DMA GEM buffer. */ + dma_obj = __drm_gem_dma_create(dev, attach->dmabuf->size, true); + if (IS_ERR(dma_obj)) + return ERR_CAST(dma_obj); - cma_obj->paddr = sg_dma_address(sgt->sgl); - cma_obj->sgt = sgt; + dma_obj->paddr = sg_dma_address(sgt->sgl); + dma_obj->sgt = sgt; - DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, attach->dmabuf->size); + DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->paddr, attach->dmabuf->size); - return &cma_obj->base; + return &dma_obj->base; } -EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table); +EXPORT_SYMBOL_GPL(drm_gem_dma_prime_import_sg_table); /** - * drm_gem_cma_vmap - map a CMA GEM object into the kernel's virtual + * drm_gem_dma_vmap - map a DMA GEM object into the kernel's virtual * address space - * @cma_obj: CMA GEM object - * @map: Returns the kernel virtual address of the CMA GEM object's backing + * @dma_obj: DMA GEM object + * @map: Returns the kernel virtual address of the DMA GEM object's backing * store. * * This function maps a buffer into the kernel's virtual address space. - * Since the CMA buffers are already mapped into the kernel virtual address + * Since the DMA buffers are already mapped into the kernel virtual address * space this simply returns the cached virtual address. * * Returns: * 0 on success, or a negative error code otherwise. */ -int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj, +int drm_gem_dma_vmap(struct drm_gem_dma_object *dma_obj, struct iosys_map *map) { - iosys_map_set_vaddr(map, cma_obj->vaddr); + iosys_map_set_vaddr(map, dma_obj->vaddr); return 0; } -EXPORT_SYMBOL_GPL(drm_gem_cma_vmap); +EXPORT_SYMBOL_GPL(drm_gem_dma_vmap); /** - * drm_gem_cma_mmap - memory-map an exported CMA GEM object - * @cma_obj: CMA GEM object + * drm_gem_dma_mmap - memory-map an exported DMA GEM object + * @dma_obj: DMA GEM object * @vma: VMA for the area to be mapped * * This function maps a buffer into a userspace process's address space. @@ -520,9 +517,9 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_vmap); * Returns: * 0 on success or a negative error code on failure. */ -int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma) +int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct *vma) { - struct drm_gem_object *obj = &cma_obj->base; + struct drm_gem_object *obj = &dma_obj->base; int ret; /* @@ -534,37 +531,37 @@ int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct * vma->vm_flags &= ~VM_PFNMAP; vma->vm_flags |= VM_DONTEXPAND; - if (cma_obj->map_noncoherent) { + if (dma_obj->map_noncoherent) { vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - ret = dma_mmap_pages(cma_obj->base.dev->dev, + ret = dma_mmap_pages(dma_obj->base.dev->dev, vma, vma->vm_end - vma->vm_start, - virt_to_page(cma_obj->vaddr)); + virt_to_page(dma_obj->vaddr)); } else { - ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr, - cma_obj->paddr, vma->vm_end - vma->vm_start); + ret = dma_mmap_wc(dma_obj->base.dev->dev, vma, dma_obj->vaddr, + dma_obj->paddr, vma->vm_end - vma->vm_start); } if (ret) drm_gem_vm_close(vma); return ret; } -EXPORT_SYMBOL_GPL(drm_gem_cma_mmap); +EXPORT_SYMBOL_GPL(drm_gem_dma_mmap); /** - * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's + * drm_gem_dma_prime_import_sg_table_vmap - PRIME import another driver's * scatter/gather table and get the virtual address of the buffer * @dev: DRM device * @attach: DMA-BUF attachment * @sgt: Scatter/gather table of pinned pages * * This function imports a scatter/gather table using - * drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel - * virtual address. This ensures that a CMA GEM object always has its virtual + * drm_gem_dma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel + * virtual address. This ensures that a DMA GEM object always has its virtual * address set. This address is released when the object is freed. * * This function can be used as the &drm_driver.gem_prime_import_sg_table - * callback. The &DRM_GEM_CMA_DRIVER_OPS_VMAP macro provides a shortcut to set + * callback. The &DRM_GEM_DMA_DRIVER_OPS_VMAP macro provides a shortcut to set * the necessary DRM driver operations. * * Returns: @@ -572,11 +569,11 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_mmap); * error code on failure. */ struct drm_gem_object * -drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev, +drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_gem_object *obj; struct iosys_map map; int ret; @@ -587,19 +584,19 @@ drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev, return ERR_PTR(ret); } - obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt); + obj = drm_gem_dma_prime_import_sg_table(dev, attach, sgt); if (IS_ERR(obj)) { dma_buf_vunmap(attach->dmabuf, &map); return obj; } - cma_obj = to_drm_gem_cma_obj(obj); - cma_obj->vaddr = map.vaddr; + dma_obj = to_drm_gem_dma_obj(obj); + dma_obj->vaddr = map.vaddr; return obj; } -EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap); +EXPORT_SYMBOL(drm_gem_dma_prime_import_sg_table_vmap); -MODULE_DESCRIPTION("DRM CMA memory-management helpers"); +MODULE_DESCRIPTION("DRM DMA memory-management helpers"); MODULE_IMPORT_NS(DMA_BUF); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 2f61f53d472f..2ecaf3cb7afb 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -1136,7 +1136,7 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, /* * Even though it's not the SPI device that does DMA (the master does), * the dma mask is necessary for the dma_alloc_wc() in the GEM code - * (e.g., drm_gem_cma_create()). The dma_addr returned will be a physical + * (e.g., drm_gem_dma_create()). The dma_addr returned will be a physical * address which might be different from the bus address, but this is * not a problem since the address will not be used. * The virtual address is used in the transfer and the SPI core diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig index e95e96c565ba..5ca71ef87325 100644 --- a/drivers/gpu/drm/fsl-dcu/Kconfig +++ b/drivers/gpu/drm/fsl-dcu/Kconfig @@ -3,7 +3,7 @@ config DRM_FSL_DCU tristate "DRM Support for Freescale DCU" depends on DRM && OF && ARM && COMMON_CLK select BACKLIGHT_CLASS_DEVICE - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL select REGMAP_MMIO diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 4baa4977e473..b4acc3422ba4 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -21,7 +21,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> @@ -149,13 +149,13 @@ static void fsl_dcu_unload(struct drm_device *dev) dev->dev_private = NULL; } -DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(fsl_dcu_drm_fops); static const struct drm_driver fsl_dcu_drm_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .load = fsl_dcu_load, .unload = fsl_dcu_unload, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fsl_dcu_drm_fops, .name = "fsl-dcu-drm", .desc = "Freescale DCU DRM", diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index aba2b714e8a6..48c98331a3c0 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -13,7 +13,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> @@ -84,7 +84,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); struct drm_framebuffer *fb = plane->state->fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned int alpha = DCU_LAYER_AB_NONE, bpp; int index; diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig b/drivers/gpu/drm/hisilicon/kirin/Kconfig index b770f7662830..c5265675bf0c 100644 --- a/drivers/gpu/drm/hisilicon/kirin/Kconfig +++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig @@ -3,7 +3,7 @@ config DRM_HISI_KIRIN tristate "DRM Support for Hisilicon Kirin series SoCs Platform" depends on DRM && OF && ARM64 select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DSI help Choose this option if you have a hisilicon Kirin chipsets(hi6220). diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index c5d304826c3b..9666d71a83cc 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -27,7 +27,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -548,7 +548,7 @@ static const struct drm_crtc_funcs ade_crtc_funcs = { static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, u32 ch, u32 y, u32 in_h, u32 fmt) { - struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, 0); u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; u32 stride = fb->pitches[0]; u32 addr = (u32)obj->paddr + y * stride; @@ -919,12 +919,12 @@ static const struct drm_mode_config_funcs ade_mode_config_funcs = { }; -DEFINE_DRM_GEM_CMA_FOPS(ade_fops); +DEFINE_DRM_GEM_DMA_FOPS(ade_fops); static const struct drm_driver ade_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ade_fops, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .name = "kirin", .desc = "Hisilicon Kirin620 SoC DRM Driver", .date = "20150718", diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index e8b0fe970969..73ee7f25f734 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -20,7 +20,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index bb9738c7c825..975de4ff7313 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -3,7 +3,7 @@ config DRM_IMX tristate "DRM Support for Freescale i.MX" select DRM_KMS_HELPER select VIDEOMODE_HELPERS - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST) depends on IMX_IPUV3_CORE diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig index 5c2b2277afbf..3ffc061d392b 100644 --- a/drivers/gpu/drm/imx/dcss/Kconfig +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -2,7 +2,7 @@ config DRM_IMX_DCSS tristate "i.MX8MQ DCSS" select IMX_IRQSTEER select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS depends on DRM && ARCH_MXC && ARM64 help diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c index 9b84df34a6a1..f50814e9d549 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-kms.c +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c @@ -8,7 +8,7 @@ #include <drm/drm_bridge_connector.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> @@ -17,7 +17,7 @@ #include "dcss-dev.h" #include "dcss-kms.h" -DEFINE_DRM_GEM_CMA_FOPS(dcss_cma_fops); +DEFINE_DRM_GEM_DMA_FOPS(dcss_cma_fops); static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = { .fb_create = drm_gem_fb_create, @@ -28,7 +28,7 @@ static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = { static const struct drm_driver dcss_kms_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &dcss_cma_fops, .name = "imx-dcss", .desc = "i.MX8MQ Display Subsystem", diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c index a333c13c9ebc..4c41c93ac900 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-plane.c +++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c @@ -9,7 +9,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "dcss-dev.h" #include "dcss-kms.h" @@ -147,7 +147,7 @@ static int dcss_plane_atomic_check(struct drm_plane *plane, struct dcss_dev *dcss = plane->dev->dev_private; struct drm_framebuffer *fb = new_plane_state->fb; bool is_primary_plane = plane->type == DRM_PLANE_TYPE_PRIMARY; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_crtc_state *crtc_state; int hdisplay, vdisplay; int min, max; @@ -156,8 +156,8 @@ static int dcss_plane_atomic_check(struct drm_plane *plane, if (!fb || !new_plane_state->crtc) return 0; - cma_obj = drm_fb_dma_get_gem_obj(fb, 0); - WARN_ON(!cma_obj); + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + WARN_ON(!dma_obj); crtc_state = drm_atomic_get_existing_crtc_state(state, new_plane_state->crtc); @@ -218,26 +218,26 @@ static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) struct dcss_dev *dcss = plane->dev->dev_private; struct drm_framebuffer *fb = state->fb; const struct drm_format_info *format = fb->format; - struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); unsigned long p1_ba = 0, p2_ba = 0; if (!format->is_yuv || format->format == DRM_FORMAT_NV12 || format->format == DRM_FORMAT_NV21) - p1_ba = cma_obj->paddr + fb->offsets[0] + + p1_ba = dma_obj->paddr + fb->offsets[0] + fb->pitches[0] * (state->src.y1 >> 16) + format->char_per_block[0] * (state->src.x1 >> 16); else if (format->format == DRM_FORMAT_UYVY || format->format == DRM_FORMAT_VYUY || format->format == DRM_FORMAT_YUYV || format->format == DRM_FORMAT_YVYU) - p1_ba = cma_obj->paddr + fb->offsets[0] + + p1_ba = dma_obj->paddr + fb->offsets[0] + fb->pitches[0] * (state->src.y1 >> 16) + 2 * format->char_per_block[0] * (state->src.x1 >> 17); if (format->format == DRM_FORMAT_NV12 || format->format == DRM_FORMAT_NV21) - p2_ba = cma_obj->paddr + fb->offsets[1] + + p2_ba = dma_obj->paddr + fb->offsets[1] + (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) + (state->src.x1 >> 17)) << 1); diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index e43345bd1346..8dd8b0f912af 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -17,7 +17,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_of.h> @@ -32,7 +32,7 @@ static int legacyfb_depth = 16; module_param(legacyfb_depth, int, 0444); -DEFINE_DRM_GEM_CMA_FOPS(imx_drm_driver_fops); +DEFINE_DRM_GEM_DMA_FOPS(imx_drm_driver_fops); void imx_drm_connector_destroy(struct drm_connector *connector) { @@ -152,7 +152,7 @@ static int imx_drm_dumb_create(struct drm_file *file_priv, args->width = ALIGN(width, 8); - ret = drm_gem_cma_dumb_create(file_priv, drm, args); + ret = drm_gem_dma_dumb_create(file_priv, drm, args); if (ret) return ret; @@ -162,7 +162,7 @@ static int imx_drm_dumb_create(struct drm_file *file_priv, static const struct drm_driver imx_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create), .ioctls = imx_drm_ioctls, .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), .fops = &imx_drm_driver_fops, diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h index c3e1a3f14d30..e721bebda2bd 100644 --- a/drivers/gpu/drm/imx/imx-drm.h +++ b/drivers/gpu/drm/imx/imx-drm.h @@ -32,7 +32,7 @@ extern struct platform_driver ipu_drm_driver; void imx_drm_mode_config_init(struct drm_device *drm); -struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); +struct drm_gem_dma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); int imx_drm_encoder_parse_of(struct drm_device *drm, struct drm_encoder *encoder, struct device_node *np); diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index d9f832f952c2..5f26090b0c98 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -18,7 +18,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 27bd16418002..07c0b9def383 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -12,7 +12,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <video/imx-ipu-v3.h> @@ -125,14 +125,14 @@ static inline unsigned long drm_plane_state_to_eba(struct drm_plane_state *state, int plane) { struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_dma_get_gem_obj(fb, plane); - BUG_ON(!cma_obj); + dma_obj = drm_fb_dma_get_gem_obj(fb, plane); + BUG_ON(!dma_obj); - return cma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y + + return dma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y + fb->format->cpp[plane] * x; } @@ -140,18 +140,18 @@ static inline unsigned long drm_plane_state_to_ubo(struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; unsigned long eba = drm_plane_state_to_eba(state, 0); int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_dma_get_gem_obj(fb, 1); - BUG_ON(!cma_obj); + dma_obj = drm_fb_dma_get_gem_obj(fb, 1); + BUG_ON(!dma_obj); x /= fb->format->hsub; y /= fb->format->vsub; - return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + + return dma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + fb->format->cpp[1] * x - eba; } @@ -159,18 +159,18 @@ static inline unsigned long drm_plane_state_to_vbo(struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; unsigned long eba = drm_plane_state_to_eba(state, 0); int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_dma_get_gem_obj(fb, 2); - BUG_ON(!cma_obj); + dma_obj = drm_fb_dma_get_gem_obj(fb, 2); + BUG_ON(!dma_obj); x /= fb->format->hsub; y /= fb->format->vsub; - return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + + return dma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + fb->format->cpp[2] * x - eba; } diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig index 090830bcbde7..a53f475d33df 100644 --- a/drivers/gpu/drm/ingenic/Kconfig +++ b/drivers/gpu/drm/ingenic/Kconfig @@ -8,7 +8,7 @@ config DRM_INGENIC select DRM_BRIDGE select DRM_PANEL_BRIDGE select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help Choose this option for DRM support for the Ingenic SoCs. diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 1dd78145b4b9..ab0515d2c420 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -30,7 +30,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_encoder.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> @@ -914,7 +914,7 @@ static struct drm_gem_object * ingenic_drm_gem_create_object(struct drm_device *drm, size_t size) { struct ingenic_drm *priv = drm_device_get_priv(drm); - struct drm_gem_cma_object *obj; + struct drm_gem_dma_object *obj; obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (!obj) @@ -947,7 +947,7 @@ static void ingenic_drm_destroy_state(struct drm_private_obj *obj, kfree(priv_state); } -DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(ingenic_drm_fops); static const struct drm_driver ingenic_drm_driver_data = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, @@ -960,7 +960,7 @@ static const struct drm_driver ingenic_drm_driver_data = { .fops = &ingenic_drm_fops, .gem_create_object = ingenic_drm_gem_create_object, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, }; static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = { diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 21052600cef4..7a43505011a5 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -26,7 +26,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane.h> #include <drm/drm_property.h> diff --git a/drivers/gpu/drm/kmb/Kconfig b/drivers/gpu/drm/kmb/Kconfig index 5fdd43dad507..fd011367db1d 100644 --- a/drivers/gpu/drm/kmb/Kconfig +++ b/drivers/gpu/drm/kmb/Kconfig @@ -3,7 +3,7 @@ config DRM_KMB_DISPLAY depends on DRM depends on ARCH_KEEMBAY || COMPILE_TEST select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DSI help Choose this option if you have Intel's KeemBay SOC which integrates diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c index 76fef0880504..2382ccb3ee99 100644 --- a/drivers/gpu/drm/kmb/kmb_drv.c +++ b/drivers/gpu/drm/kmb/kmb_drv.c @@ -16,7 +16,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> @@ -433,14 +433,14 @@ static void kmb_irq_uninstall(struct drm_device *drm) free_irq(kmb->irq_lcd, drm); } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver kmb_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, /* GEM Operations */ .fops = &fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .name = "kmb-drm", .desc = "KEEMBAY DISPLAY DRIVER", .date = DRIVER_DATE, diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c index ca3246e48e45..a42f63f6f957 100644 --- a/drivers/gpu/drm/kmb/kmb_plane.c +++ b/drivers/gpu/drm/kmb/kmb_plane.c @@ -12,7 +12,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include "kmb_drv.h" diff --git a/drivers/gpu/drm/logicvc/Kconfig b/drivers/gpu/drm/logicvc/Kconfig index 73be27cc749c..fa7a88368809 100644 --- a/drivers/gpu/drm/logicvc/Kconfig +++ b/drivers/gpu/drm/logicvc/Kconfig @@ -4,6 +4,6 @@ config DRM_LOGICVC depends on OF || COMPILE_TEST select DRM_KMS_HELPER select DRM_KMS_DMA_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER help DRM display driver for the logiCVC programmable logic block from Xylon diff --git a/drivers/gpu/drm/logicvc/logicvc_crtc.c b/drivers/gpu/drm/logicvc/logicvc_crtc.c index c94bb9bb456b..43a675d03808 100644 --- a/drivers/gpu/drm/logicvc/logicvc_crtc.c +++ b/drivers/gpu/drm/logicvc/logicvc_crtc.c @@ -12,7 +12,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_drv.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/logicvc/logicvc_drm.c b/drivers/gpu/drm/logicvc/logicvc_drm.c index 65a050176c33..cc9a4e965f77 100644 --- a/drivers/gpu/drm/logicvc/logicvc_drm.c +++ b/drivers/gpu/drm/logicvc/logicvc_drm.c @@ -18,7 +18,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_print.h> #include "logicvc_crtc.h" @@ -29,9 +29,9 @@ #include "logicvc_of.h" #include "logicvc_regs.h" -DEFINE_DRM_GEM_CMA_FOPS(logicvc_drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(logicvc_drm_fops); -static int logicvc_drm_gem_cma_dumb_create(struct drm_file *file_priv, +static int logicvc_drm_gem_dma_dumb_create(struct drm_file *file_priv, struct drm_device *drm_dev, struct drm_mode_create_dumb *args) { @@ -40,7 +40,7 @@ static int logicvc_drm_gem_cma_dumb_create(struct drm_file *file_priv, /* Stride is always fixed to its configuration value. */ args->pitch = logicvc->config.row_stride * DIV_ROUND_UP(args->bpp, 8); - return drm_gem_cma_dumb_create_internal(file_priv, drm_dev, args); + return drm_gem_dma_dumb_create_internal(file_priv, drm_dev, args); } static struct drm_driver logicvc_drm_driver = { @@ -54,7 +54,7 @@ static struct drm_driver logicvc_drm_driver = { .major = 1, .minor = 0, - DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(logicvc_drm_gem_cma_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(logicvc_drm_gem_dma_dumb_create), }; static struct regmap_config logicvc_drm_regmap_config = { diff --git a/drivers/gpu/drm/logicvc/logicvc_interface.c b/drivers/gpu/drm/logicvc/logicvc_interface.c index c73592f6c406..815cebb4c4ca 100644 --- a/drivers/gpu/drm/logicvc/logicvc_interface.c +++ b/drivers/gpu/drm/logicvc/logicvc_interface.c @@ -12,7 +12,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> #include <drm/drm_encoder.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/logicvc/logicvc_mode.c b/drivers/gpu/drm/logicvc/logicvc_mode.c index c59da7039dc1..d8207ffda1af 100644 --- a/drivers/gpu/drm/logicvc/logicvc_mode.c +++ b/drivers/gpu/drm/logicvc/logicvc_mode.c @@ -11,7 +11,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_mode_config.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/mcde/Kconfig b/drivers/gpu/drm/mcde/Kconfig index d0bf1bc8da3f..4f3d68e11bc1 100644 --- a/drivers/gpu/drm/mcde/Kconfig +++ b/drivers/gpu/drm/mcde/Kconfig @@ -10,7 +10,7 @@ config DRM_MCDE select DRM_BRIDGE select DRM_PANEL_BRIDGE select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help Choose this option for DRM support for the ST-Ericsson MCDE diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 9247da47f0cf..52043a12a2e8 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -15,7 +15,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_bridge.h> diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index 509c2b03bc42..1c4482ad507d 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -71,7 +71,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_of.h> @@ -198,7 +198,7 @@ static int mcde_modeset_init(struct drm_device *drm) return 0; } -DEFINE_DRM_GEM_CMA_FOPS(drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(drm_fops); static const struct drm_driver mcde_drm_driver = { .driver_features = @@ -212,7 +212,7 @@ static const struct drm_driver mcde_drm_driver = { .major = 1, .minor = 0, .patchlevel = 0, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, }; static int mcde_drm_bind(struct device *dev) diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 2976d21e9a34..6d7d0e207082 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -7,7 +7,7 @@ config DRM_MEDIATEK depends on HAVE_ARM_SMCCC depends on OF depends on MTK_MMSYS - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 0e4c77724b05..5f02f8d0e4fc 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -20,7 +20,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 139d7724c6d0..47e96b0289f9 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -8,7 +8,7 @@ #include <drm/drm.h> #include <drm/drm_device.h> #include <drm/drm_gem.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_prime.h> #include "mtk_drm_drv.h" @@ -22,7 +22,7 @@ static const struct drm_gem_object_funcs mtk_drm_gem_object_funcs = { .vmap = mtk_drm_gem_prime_vmap, .vunmap = mtk_drm_gem_prime_vunmap, .mmap = mtk_drm_gem_object_mmap, - .vm_ops = &drm_gem_cma_vm_ops, + .vm_ops = &drm_gem_dma_vm_ops, }; static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig index 6c70fc3214af..823909da87db 100644 --- a/drivers/gpu/drm/meson/Kconfig +++ b/drivers/gpu/drm/meson/Kconfig @@ -4,7 +4,7 @@ config DRM_MESON depends on DRM && OF && (ARM || ARM64) depends on ARCH_MESON || COMPILE_TEST select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_DISPLAY_CONNECTOR select VIDEOMODE_HELPERS select REGMAP_MMIO diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 1b70938cfd2c..ef386d7b9450 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_module.h> @@ -87,16 +87,16 @@ static int meson_dumb_create(struct drm_file *file, struct drm_device *dev, args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), SZ_64); args->size = PAGE_ALIGN(args->pitch * args->height); - return drm_gem_cma_dumb_create_internal(file, dev, args); + return drm_gem_dma_dumb_create_internal(file, dev, args); } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver meson_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - /* CMA Ops */ - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(meson_dumb_create), + /* DMA Ops */ + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(meson_dumb_create), /* Misc */ .fops = &fops, diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index bfebf45d8402..9d3ab4a80b1c 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -15,7 +15,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "meson_overlay.h" #include "meson_registers.h" @@ -476,7 +476,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, plane); struct drm_framebuffer *fb = new_state->fb; struct meson_drm *priv = meson_overlay->priv; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned long flags; bool interlace_mode; diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 51479715cce7..f7b9f63a1e70 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -19,7 +19,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "meson_plane.h" #include "meson_registers.h" @@ -139,7 +139,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane, struct drm_rect dest = drm_plane_state_dest(new_state); struct meson_drm *priv = meson_plane->priv; struct drm_framebuffer *fb = new_state->fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned long flags; int vsc_ini_rcv_num, vsc_ini_rpt_p0_num; int vsc_bot_rcv_num, vsc_bot_rpt_p0_num; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 1ed4cd09dbf8..1d0bafedd585 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -355,7 +355,7 @@ static int msm_init_vram(struct drm_device *dev) DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start); /* if we have no IOMMU, then we need to use carveout allocator. - * Grab the entire CMA chunk carved out in early startup in + * Grab the entire DMA chunk carved out in early startup in * mach-msm: */ } else if (!msm_use_mmu(dev)) { diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index 873551b4552f..116f8168bda4 100644 --- a/drivers/gpu/drm/mxsfb/Kconfig +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -10,7 +10,7 @@ config DRM_MXSFB depends on COMMON_CLK select DRM_MXS select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_PANEL select DRM_PANEL_BRIDGE help @@ -26,7 +26,7 @@ config DRM_IMX_LCDIF depends on COMMON_CLK select DRM_MXS select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_PANEL select DRM_PANEL_BRIDGE help diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c index befad33dcb95..05db135800db 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_drv.c +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c @@ -20,7 +20,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_mode_config.h> #include <drm/drm_module.h> @@ -199,11 +199,11 @@ static void lcdif_unload(struct drm_device *drm) drm->dev_private = NULL; } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver lcdif_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fops, .name = "imx-lcdif", .desc = "i.MX LCDIF Controller DRM", diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index 0df418774035..c7efc0d27f0e 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -21,7 +21,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_plane.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 55aad92e08ba..b29b332ed381 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -22,7 +22,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_mode_config.h> #include <drm/drm_module.h> @@ -324,11 +324,11 @@ static void mxsfb_unload(struct drm_device *drm) pm_runtime_disable(drm->dev); } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver mxsfb_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fops, .name = "mxsfb-drm", .desc = "MXSFB Controller DRM", diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index e55e9262afb2..0bff493bf2a8 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -24,7 +24,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_plane.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index a9043eacce97..584a69f99af6 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -166,7 +166,7 @@ config DRM_PANEL_ILITEK_ILI9341 tristate "Ilitek ILI9341 240x320 QVGA panels" depends on OF && SPI depends on DRM_KMS_HELPER - depends on DRM_GEM_CMA_HELPER + depends on DRM_GEM_DMA_HELPER depends on BACKLIGHT_CLASS_DEVICE select DRM_MIPI_DBI help diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index 6826f4d4826a..7da09e34385d 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -32,7 +32,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_modes.h> @@ -586,12 +586,12 @@ static const struct drm_display_mode ili9341_dbi_mode = { DRM_SIMPLE_MODE(240, 320, 37, 49), }; -DEFINE_DRM_GEM_CMA_FOPS(ili9341_dbi_fops); +DEFINE_DRM_GEM_DMA_FOPS(ili9341_dbi_fops); static struct drm_driver ili9341_dbi_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ili9341_dbi_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "ili9341", .desc = "Ilitek ILI9341", diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig index 91ee05b01303..ad24cdf1d992 100644 --- a/drivers/gpu/drm/pl111/Kconfig +++ b/drivers/gpu/drm/pl111/Kconfig @@ -6,7 +6,7 @@ config DRM_PL111 depends on VEXPRESS_CONFIG || VEXPRESS_CONFIG=n depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_BRIDGE select DRM_PANEL_BRIDGE select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index 5f2429c3633e..6afdf260a4e2 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -19,7 +19,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_vblank.h> #include "pl111_drm.h" diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 5b5f3573b619..eb25eedb5ee0 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -50,7 +50,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> @@ -207,10 +207,10 @@ pl111_gem_import_sg_table(struct drm_device *dev, if (priv->use_device_memory) return ERR_PTR(-EINVAL); - return drm_gem_cma_prime_import_sg_table(dev, attach, sgt); + return drm_gem_dma_prime_import_sg_table(dev, attach, sgt); } -DEFINE_DRM_GEM_CMA_FOPS(drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(drm_fops); static const struct drm_driver pl111_drm_driver = { .driver_features = @@ -223,7 +223,7 @@ static const struct drm_driver pl111_drm_driver = { .major = 1, .minor = 0, .patchlevel = 0, - .dumb_create = drm_gem_cma_dumb_create, + .dumb_create = drm_gem_dma_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import_sg_table = pl111_gem_import_sg_table, diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index f6e6a6d5d987..c959e8c6be7d 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -5,7 +5,7 @@ config DRM_RCAR_DU depends on ARM || ARM64 depends on ARCH_RENESAS || COMPILE_TEST select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help Choose this option if you have an R-Car chipset. diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index ed887ebd2f6b..fd3b94649a01 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -17,7 +17,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_vblank.h> #include "rcar_cmm.h" diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 110ec9538b44..00ac233a115e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -21,7 +21,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> @@ -578,7 +578,7 @@ const char *rcar_du_output_name(enum rcar_du_output output) * DRM operations */ -DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops); +DEFINE_DRM_GEM_DMA_FOPS(rcar_du_fops); static const struct drm_driver rcar_du_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 7fed5b0c65ce..c9b8c4e03c25 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -12,7 +12,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_device.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> @@ -327,12 +327,12 @@ const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc) */ static const struct drm_gem_object_funcs rcar_du_gem_funcs = { - .free = drm_gem_cma_object_free, - .print_info = drm_gem_cma_object_print_info, - .get_sg_table = drm_gem_cma_object_get_sg_table, - .vmap = drm_gem_cma_object_vmap, - .mmap = drm_gem_cma_object_mmap, - .vm_ops = &drm_gem_cma_vm_ops, + .free = drm_gem_dma_object_free, + .print_info = drm_gem_dma_object_print_info, + .get_sg_table = drm_gem_dma_object_get_sg_table, + .vmap = drm_gem_dma_object_vmap, + .mmap = drm_gem_dma_object_mmap, + .vm_ops = &drm_gem_dma_vm_ops, }; struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev, @@ -340,33 +340,33 @@ struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev, struct sg_table *sgt) { struct rcar_du_device *rcdu = to_rcar_du_device(dev); - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_gem_object *gem_obj; int ret; if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) - return drm_gem_cma_prime_import_sg_table(dev, attach, sgt); + return drm_gem_dma_prime_import_sg_table(dev, attach, sgt); - /* Create a CMA GEM buffer. */ - cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); - if (!cma_obj) + /* Create a DMA GEM buffer. */ + dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL); + if (!dma_obj) return ERR_PTR(-ENOMEM); - gem_obj = &cma_obj->base; + gem_obj = &dma_obj->base; gem_obj->funcs = &rcar_du_gem_funcs; drm_gem_private_object_init(dev, gem_obj, attach->dmabuf->size); - cma_obj->map_noncoherent = false; + dma_obj->map_noncoherent = false; ret = drm_gem_create_mmap_offset(gem_obj); if (ret) { drm_gem_object_release(gem_obj); - kfree(cma_obj); + kfree(dma_obj); return ERR_PTR(ret); } - cma_obj->paddr = 0; - cma_obj->sgt = sgt; + dma_obj->paddr = 0; + dma_obj->sgt = sgt; return gem_obj; } @@ -389,7 +389,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev, args->pitch = roundup(min_pitch, align); - return drm_gem_cma_dumb_create_internal(file, dev, args); + return drm_gem_dma_dumb_create_internal(file, dev, args); } static struct drm_framebuffer * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 4ae444346991..31024f50cd23 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -15,7 +15,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "rcar_du_drv.h" #include "rcar_du_group.h" @@ -341,7 +341,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp, if (state->source == RCAR_DU_PLANE_MEMORY) { struct drm_framebuffer *fb = state->state.fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned int i; if (state->format->planes == 2) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 99d32f42e46d..0f6c0a08e74d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -15,7 +15,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_vblank.h> @@ -183,7 +183,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, int ret; for (i = 0; i < fb->format->num_planes; ++i) { - struct drm_gem_cma_object *gem = drm_fb_dma_get_gem_obj(fb, i); + struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); struct sg_table *sgt = &sg_tables[i]; if (gem->sgt) { diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 53c2d9980d48..1bf3e2829cd0 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -2,7 +2,7 @@ config DRM_ROCKCHIP tristate "DRM Support for Rockchip" depends on DRM && ROCKCHIP_IOMMU - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 67d38f53d3e5..49831c738d4d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -18,7 +18,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 985584147da1..614e97aaac80 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -10,7 +10,7 @@ #include <drm/drm.h> #include <drm/drm_gem.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_prime.h> #include <drm/drm_vma_manager.h> @@ -279,7 +279,7 @@ static const struct drm_gem_object_funcs rockchip_gem_object_funcs = { .vmap = rockchip_gem_prime_vmap, .vunmap = rockchip_gem_prime_vunmap, .mmap = rockchip_drm_gem_object_mmap, - .vm_ops = &drm_gem_cma_vm_ops, + .vm_ops = &drm_gem_dma_vm_ops, }; static struct rockchip_gem_object * diff --git a/drivers/gpu/drm/shmobile/Kconfig b/drivers/gpu/drm/shmobile/Kconfig index 288b838a904a..4ec5dc74a6b0 100644 --- a/drivers/gpu/drm/shmobile/Kconfig +++ b/drivers/gpu/drm/shmobile/Kconfig @@ -5,7 +5,7 @@ config DRM_SHMOBILE depends on ARCH_SHMOBILE || COMPILE_TEST select BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER help Choose this option if you have an SH Mobile chipset. If M is selected the module will be called shmob-drm. diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 94318f858ed6..bdf3e8841a40 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -15,7 +15,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> @@ -288,7 +288,7 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc, { struct drm_crtc *crtc = &scrtc->crtc; struct drm_framebuffer *fb = crtc->primary->fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned int bpp; bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 731cbad7520f..3d511fa38913 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -17,7 +17,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> @@ -126,11 +126,11 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg) return IRQ_HANDLED; } -DEFINE_DRM_GEM_CMA_FOPS(shmob_drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(shmob_drm_fops); static const struct drm_driver shmob_drm_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &shmob_drm_fops, .name = "shmob-drm", .desc = "Renesas SH Mobile DRM", diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/shmobile/shmob_drm_kms.c index edb003537530..60a2c8d8a0d9 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_kms.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.c @@ -10,7 +10,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.h b/drivers/gpu/drm/shmobile/shmob_drm_kms.h index 6ec2b732bb94..0347b1fd2338 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_kms.h +++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.h @@ -12,7 +12,7 @@ #include <linux/types.h> -struct drm_gem_cma_object; +struct drm_gem_dma_object; struct shmob_drm_device; struct shmob_drm_format_info { diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 6fa64bce0c91..6d167e858d86 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -12,7 +12,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "shmob_drm_drv.h" #include "shmob_drm_kms.h" @@ -41,7 +41,7 @@ static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane, struct drm_framebuffer *fb, int x, int y) { - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned int bpp; bpp = splane->format->yuv ? 8 : splane->format->bpp; diff --git a/drivers/gpu/drm/sprd/Kconfig b/drivers/gpu/drm/sprd/Kconfig index 9a9c7ebfc716..e22b780fe822 100644 --- a/drivers/gpu/drm/sprd/Kconfig +++ b/drivers/gpu/drm/sprd/Kconfig @@ -2,7 +2,7 @@ config DRM_SPRD tristate "DRM Support for Unisoc SoCs Platform" depends on ARCH_SPRD || COMPILE_TEST depends on DRM && OF - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_MIPI_DSI select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c index 5ea104e0beb8..44c0fba93607 100644 --- a/drivers/gpu/drm/sprd/sprd_dpu.c +++ b/drivers/gpu/drm/sprd/sprd_dpu.c @@ -21,7 +21,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include "sprd_drm.h" @@ -323,7 +323,7 @@ static u32 drm_blend_to_dpu(struct drm_plane_state *state) static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state) { struct dpu_context *ctx = &dpu->ctx; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_framebuffer *fb = state->fb; u32 addr, size, offset, pitch, blend, format, rotation; u32 src_x = state->src_x >> 16; @@ -340,8 +340,8 @@ static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state) size = (src_w & 0xffff) | (src_h << 16); for (i = 0; i < fb->format->num_planes; i++) { - cma_obj = drm_fb_dma_get_gem_obj(fb, i); - addr = cma_obj->paddr + fb->offsets[i]; + dma_obj = drm_fb_dma_get_gem_obj(fb, i); + addr = dma_obj->paddr + fb->offsets[i]; if (i == 0) layer_reg_wr(ctx, REG_LAY_BASE_ADDR0, addr, index); diff --git a/drivers/gpu/drm/sprd/sprd_drm.c b/drivers/gpu/drm/sprd/sprd_drm.c index b8fc1c6a0cb8..9d42f17a5734 100644 --- a/drivers/gpu/drm/sprd/sprd_drm.c +++ b/drivers/gpu/drm/sprd/sprd_drm.c @@ -13,7 +13,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> @@ -48,14 +48,14 @@ static void sprd_drm_mode_config_init(struct drm_device *drm) drm->mode_config.helper_private = &sprd_drm_mode_config_helper; } -DEFINE_DRM_GEM_CMA_FOPS(sprd_drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(sprd_drm_fops); static struct drm_driver sprd_drm_drv = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &sprd_drm_fops, /* GEM Operations */ - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index 246a94afbe74..f2a880c48485 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig @@ -4,7 +4,7 @@ config DRM_STI depends on OF && DRM && (ARCH_STI || ARCH_MULTIPLATFORM) select RESET_CONTROLLER select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_PANEL select FW_LOADER select SND_SOC_HDMI_CODEC if SND_SOC diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index d374fa50be60..db0a1eb53532 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -13,7 +13,7 @@ #include <drm/drm_device.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "sti_compositor.h" #include "sti_cursor.h" @@ -244,7 +244,7 @@ static int sti_cursor_atomic_check(struct drm_plane *drm_plane, } if (!drm_fb_dma_get_gem_obj(fb, 0)) { - DRM_ERROR("Can't get CMA GEM object for fb\n"); + DRM_ERROR("Can't get DMA GEM object for fb\n"); return -EINVAL; } @@ -267,7 +267,7 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane, struct drm_framebuffer *fb = newstate->fb; struct drm_display_mode *mode; int dst_x, dst_y; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; u32 y, x; u32 val; @@ -278,10 +278,10 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane, dst_x = newstate->crtc_x; dst_y = newstate->crtc_y; - cma_obj = drm_fb_dma_get_gem_obj(fb, 0); + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); /* Convert ARGB8888 to CLUT8 */ - sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr); + sti_cursor_argb8888_to_clut8(cursor, (u32 *)dma_obj->vaddr); /* AWS and AWE depend on the mode */ y = sti_vtg_get_line_number(*mode, 0); diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index c0fbdb8cf6eb..7abf010a3293 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -15,7 +15,7 @@ #include <drm/drm_debugfs.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> @@ -127,12 +127,12 @@ static void sti_mode_config_init(struct drm_device *dev) dev->mode_config.normalize_zpos = true; } -DEFINE_DRM_GEM_CMA_FOPS(sti_driver_fops); +DEFINE_DRM_GEM_DMA_FOPS(sti_driver_fops); static const struct drm_driver sti_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .fops = &sti_driver_fops, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .debugfs_init = sti_drm_dbg_init, diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 623a09163f9f..3ce9d4992176 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -15,7 +15,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "sti_compositor.h" #include "sti_gdp.h" @@ -659,7 +659,7 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, } if (!drm_fb_dma_get_gem_obj(fb, 0)) { - DRM_ERROR("Can't get CMA GEM object for fb\n"); + DRM_ERROR("Can't get DMA GEM object for fb\n"); return -EINVAL; } @@ -714,7 +714,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, struct drm_display_mode *mode; int dst_x, dst_y, dst_w, dst_h; int src_x, src_y, src_w, src_h; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct sti_gdp_node_list *list; struct sti_gdp_node_list *curr_list; struct sti_gdp_node *top_field, *btm_field; @@ -778,15 +778,15 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format); top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE; - cma_obj = drm_fb_dma_get_gem_obj(fb, 0); + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, - (unsigned long)cma_obj->paddr); + (unsigned long)dma_obj->paddr); /* pixel memory location */ bpp = fb->format->cpp[0]; - top_field->gam_gdp_pml = (u32)cma_obj->paddr + fb->offsets[0]; + top_field->gam_gdp_pml = (u32)dma_obj->paddr + fb->offsets[0]; top_field->gam_gdp_pml += src_x * bpp; top_field->gam_gdp_pml += src_y * fb->pitches[0]; @@ -831,7 +831,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, dev_dbg(gdp->dev, "Current NVN:0x%X\n", readl(gdp->regs + GAM_GDP_NVN_OFFSET)); dev_dbg(gdp->dev, "Posted buff: %lx current buff: %x\n", - (unsigned long)cma_obj->paddr, + (unsigned long)dma_obj->paddr, readl(gdp->regs + GAM_GDP_PML_OFFSET)); if (!curr_list) { diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 26284c5f5b22..ee274140274d 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -19,7 +19,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "sti_compositor.h" #include "sti_drv.h" @@ -1056,7 +1056,7 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, } if (!drm_fb_dma_get_gem_obj(fb, 0)) { - DRM_ERROR("Can't get CMA GEM object for fb\n"); + DRM_ERROR("Can't get DMA GEM object for fb\n"); return -EINVAL; } @@ -1124,7 +1124,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, struct drm_display_mode *mode; int dst_x, dst_y, dst_w, dst_h; int src_x, src_y, src_w, src_h; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct sti_hqvdp_cmd *cmd; int scale_h, scale_v; int cmd_offset; @@ -1178,15 +1178,15 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT; cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT; - cma_obj = drm_fb_dma_get_gem_obj(fb, 0); + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, - (unsigned long)cma_obj->paddr); + (unsigned long)dma_obj->paddr); /* Buffer planes address */ - cmd->top.current_luma = (u32)cma_obj->paddr + fb->offsets[0]; - cmd->top.current_chroma = (u32)cma_obj->paddr + fb->offsets[1]; + cmd->top.current_luma = (u32)dma_obj->paddr + fb->offsets[0]; + cmd->top.current_chroma = (u32)dma_obj->paddr + fb->offsets[1]; /* Pitches */ cmd->top.luma_processed_pitch = fb->pitches[0]; diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c index 0a55180be22b..29e669ccec5b 100644 --- a/drivers/gpu/drm/sti/sti_plane.c +++ b/drivers/gpu/drm/sti/sti_plane.c @@ -11,7 +11,7 @@ #include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "sti_compositor.h" #include "sti_drv.h" diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig index e0379488cd0d..ded72f879482 100644 --- a/drivers/gpu/drm/stm/Kconfig +++ b/drivers/gpu/drm/stm/Kconfig @@ -3,7 +3,7 @@ config DRM_STM tristate "DRM Support for STMicroelectronics SoC Series" depends on DRM && (ARCH_STM32 || ARCH_MULTIPLATFORM) select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_PANEL_BRIDGE select VIDEOMODE_HELPERS select FB_PROVIDE_GET_FB_UNMAPPED_AREA if FB diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index bb269dad30f9..d7914f5122df 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> @@ -36,7 +36,7 @@ static const struct drm_mode_config_funcs drv_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -static int stm_gem_cma_dumb_create(struct drm_file *file, +static int stm_gem_dma_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { @@ -49,10 +49,10 @@ static int stm_gem_cma_dumb_create(struct drm_file *file, args->pitch = roundup(min_pitch, 128); args->height = roundup(args->height, 4); - return drm_gem_cma_dumb_create_internal(file, dev, args); + return drm_gem_dma_dumb_create_internal(file, dev, args); } -DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops); +DEFINE_DRM_GEM_DMA_FOPS(drv_driver_fops); static const struct drm_driver drv_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, @@ -63,7 +63,7 @@ static const struct drm_driver drv_driver = { .minor = 0, .patchlevel = 0, .fops = &drv_driver_fops, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(stm_gem_cma_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(stm_gem_dma_dumb_create), }; static int drv_load(struct drm_device *ddev) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 42a98ef73d03..03c6becda795 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -32,7 +32,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index 1c2f8909f3cd..4741d9f6544c 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig @@ -3,7 +3,7 @@ config DRM_SUN4I tristate "DRM Support for Allwinner A10 Display Engine" depends on DRM && COMMON_CLK depends on ARCH_SUNXI || COMPILE_TEST - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL select REGMAP_MMIO diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index fa4539c3b149..1fbdd4961194 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -22,7 +22,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> #include "sun4i_backend.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 382074ef1394..d06ffd99d86e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -18,7 +18,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_module.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> @@ -37,10 +37,10 @@ static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv, /* The hardware only allows even pitches for YUV buffers. */ args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), 2); - return drm_gem_cma_dumb_create_internal(file_priv, drm, args); + return drm_gem_dma_dumb_create_internal(file_priv, drm, args); } -DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); +DEFINE_DRM_GEM_DMA_FOPS(sun4i_drv_fops); static const struct drm_driver sun4i_drv_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, @@ -54,7 +54,7 @@ static const struct drm_driver sun4i_drv_driver = { .minor = 0, /* GEM Operations */ - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create), }; static int sun4i_drv_bind(struct device *dev) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 4a811e803dac..baeeda04691f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -17,7 +17,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_plane.h> #include "sun4i_drv.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index b3d1c0940406..bafee05f6b24 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -17,7 +17,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> #include "sun4i_drv.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 900c71c47a3b..090523356193 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -17,7 +17,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> #include "sun8i_mixer.h" @@ -192,7 +192,7 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel, { struct drm_plane_state *state = plane->state; struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; dma_addr_t paddr; u32 ch_base; int bpp; diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 8b5dae30c8c5..8def7e0290ce 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -10,7 +10,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> #include "sun8i_csc.h" @@ -308,7 +308,7 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, struct drm_plane_state *state = plane->state; struct drm_framebuffer *fb = state->fb; const struct drm_format_info *format = fb->format; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; u32 dx, dy, src_x, src_y; dma_addr_t paddr; u32 ch_base; diff --git a/drivers/gpu/drm/tidss/Kconfig b/drivers/gpu/drm/tidss/Kconfig index bc4fa59b6fa9..378600806167 100644 --- a/drivers/gpu/drm/tidss/Kconfig +++ b/drivers/gpu/drm/tidss/Kconfig @@ -3,7 +3,7 @@ config DRM_TIDSS depends on DRM && OF depends on ARM || ARM64 || COMPILE_TEST select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER help The TI Keystone family SoCs introduced a new generation of Display SubSystem. There is currently three Keystone family diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c index 92d2c25bb0ff..cd3c43a6c806 100644 --- a/drivers/gpu/drm/tidss/tidss_crtc.c +++ b/drivers/gpu/drm/tidss/tidss_crtc.c @@ -8,7 +8,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_vblank.h> #include "tidss_crtc.h" diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index cdd9a64f9736..6f3fa37b9ca0 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -26,7 +26,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_panel.h> #include "tidss_crtc.h" @@ -1957,7 +1957,7 @@ static dma_addr_t dispc_plane_state_paddr(const struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; u32 x = state->src_x >> 16; u32 y = state->src_y >> 16; @@ -1971,7 +1971,7 @@ static dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; u32 x = state->src_x >> 16; u32 y = state->src_y >> 16; diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c index 04cfff89ee51..15cd9b91b7e2 100644 --- a/drivers/gpu/drm/tidss/tidss_drv.c +++ b/drivers/gpu/drm/tidss/tidss_drv.c @@ -15,7 +15,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> @@ -101,13 +101,13 @@ static void tidss_release(struct drm_device *ddev) drm_kms_helper_poll_fini(ddev); } -DEFINE_DRM_GEM_CMA_FOPS(tidss_fops); +DEFINE_DRM_GEM_DMA_FOPS(tidss_fops); static const struct drm_driver tidss_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &tidss_fops, .release = tidss_release, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .name = "tidss", .desc = "TI Keystone DSS", .date = "20180215", diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index e315591eb36b..d3bd2d7a181e 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -3,7 +3,7 @@ config DRM_TILCDC tristate "DRM Support for TI LCDC Display Controller" depends on DRM && OF && ARM select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_BRIDGE select DRM_PANEL_BRIDGE select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index bd4f52242c0a..9034b9778539 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -15,7 +15,7 @@ #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_print.h> #include <drm/drm_vblank.h> @@ -64,7 +64,7 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) { struct drm_device *dev = crtc->dev; struct tilcdc_drm_private *priv = dev->dev_private; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; dma_addr_t start, end; u64 dma_base_and_ceiling; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index eee3c447fbac..f72755b8ea14 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -18,7 +18,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_mm.h> #include <drm/drm_probe_helper.h> @@ -476,11 +476,11 @@ static void tilcdc_debugfs_init(struct drm_minor *minor) } #endif -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver tilcdc_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, #ifdef CONFIG_DEBUG_FS .debugfs_init = tilcdc_debugfs_init, #endif diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 027cd87c3d0d..565957264875 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -3,7 +3,7 @@ config DRM_ARCPGU tristate "ARC PGU" depends on DRM && OF - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER help Choose this option if you have an ARC PGU controller. @@ -55,7 +55,7 @@ config DRM_PANEL_MIPI_DBI tristate "DRM support for MIPI DBI compatible panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE select VIDEOMODE_HELPERS @@ -87,7 +87,7 @@ config TINYDRM_HX8357D tristate "DRM support for HX8357D display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -100,7 +100,7 @@ config TINYDRM_ILI9163 tristate "DRM support for ILI9163 display panels" depends on DRM && SPI select BACKLIGHT_CLASS_DEVICE - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_MIPI_DBI help @@ -113,7 +113,7 @@ config TINYDRM_ILI9225 tristate "DRM support for ILI9225 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI help DRM driver for the following Ilitek ILI9225 panels: @@ -125,7 +125,7 @@ config TINYDRM_ILI9341 tristate "DRM support for ILI9341 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -138,7 +138,7 @@ config TINYDRM_ILI9486 tristate "DRM support for ILI9486 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -152,7 +152,7 @@ config TINYDRM_MI0283QT tristate "DRM support for MI0283QT" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -163,7 +163,7 @@ config TINYDRM_REPAPER tristate "DRM support for Pervasive Displays RePaper panels (V231)" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER help DRM driver for the following Pervasive Displays panels: 1.44" TFT EPD Panel (E1144CS021) @@ -177,7 +177,7 @@ config TINYDRM_ST7586 tristate "DRM support for Sitronix ST7586 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI help DRM driver for the following Sitronix ST7586 panels: @@ -189,7 +189,7 @@ config TINYDRM_ST7735R tristate "DRM support for Sitronix ST7715R/ST7735R display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c index cdf320c547fb..21d9e0bd67ba 100644 --- a/drivers/gpu/drm/tiny/arcpgu.c +++ b/drivers/gpu/drm/tiny/arcpgu.c @@ -15,7 +15,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_of.h> @@ -220,7 +220,7 @@ static void arc_pgu_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *state) { struct arcpgu_drm_private *arcpgu; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; if (!pipe->plane.state->fb) return; @@ -243,7 +243,7 @@ static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops); +DEFINE_DRM_GEM_DMA_FOPS(arcpgu_drm_ops); static int arcpgu_load(struct arcpgu_drm_private *arcpgu) { @@ -370,7 +370,7 @@ static const struct drm_driver arcpgu_drm_driver = { .minor = 0, .patchlevel = 0, .fops = &arcpgu_drm_ops, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, #ifdef CONFIG_DEBUG_FS .debugfs_init = arcpgu_debugfs_init, #endif diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index ebb025543f8d..57f229a785bf 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -20,7 +20,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> @@ -190,12 +190,12 @@ static const struct drm_display_mode yx350hv15_mode = { DRM_SIMPLE_MODE(320, 480, 60, 75), }; -DEFINE_DRM_GEM_CMA_FOPS(hx8357d_fops); +DEFINE_DRM_GEM_DMA_FOPS(hx8357d_fops); static const struct drm_driver hx8357d_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &hx8357d_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "hx8357d", .desc = "HX8357D", diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index fc8ed245b0bc..86439e50e304 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -11,7 +11,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> @@ -110,12 +110,12 @@ static const struct drm_display_mode yx240qv29_mode = { DRM_SIMPLE_MODE(128, 160, 28, 35), }; -DEFINE_DRM_GEM_CMA_FOPS(ili9163_fops); +DEFINE_DRM_GEM_DMA_FOPS(ili9163_fops); static struct drm_driver ili9163_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ili9163_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "ili9163", .desc = "Ilitek ILI9163", diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index fc73ffa46a19..a79da2b4af64 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -24,7 +24,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_rect.h> @@ -78,7 +78,7 @@ static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data) static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { - struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; @@ -104,7 +104,7 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) if (ret) goto err_msg; } else { - tr = cma_obj->vaddr; + tr = dma_obj->vaddr; } switch (dbidev->rotation) { @@ -335,12 +335,12 @@ static const struct drm_display_mode ili9225_mode = { DRM_SIMPLE_MODE(176, 220, 35, 44), }; -DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops); +DEFINE_DRM_GEM_DMA_FOPS(ili9225_fops); static const struct drm_driver ili9225_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ili9225_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .name = "ili9225", .desc = "Ilitek ILI9225", .date = "20171106", diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index 5b8cc770ee7b..b8826a0b086b 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -19,7 +19,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> @@ -146,12 +146,12 @@ static const struct drm_display_mode yx240qv29_mode = { DRM_SIMPLE_MODE(240, 320, 37, 49), }; -DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops); +DEFINE_DRM_GEM_DMA_FOPS(ili9341_fops); static const struct drm_driver ili9341_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ili9341_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "ili9341", .desc = "Ilitek ILI9341", diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index 6d655e18e0aa..a5b433a8e0d8 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -18,7 +18,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> @@ -159,12 +159,12 @@ static const struct drm_display_mode waveshare_mode = { DRM_SIMPLE_MODE(480, 320, 73, 49), }; -DEFINE_DRM_GEM_CMA_FOPS(ili9486_fops); +DEFINE_DRM_GEM_DMA_FOPS(ili9486_fops); static const struct drm_driver ili9486_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ili9486_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "ili9486", .desc = "Ilitek ILI9486", diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 5e060f6910bb..27f1bd4da2f4 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -17,7 +17,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> @@ -150,12 +150,12 @@ static const struct drm_display_mode mi0283qt_mode = { DRM_SIMPLE_MODE(320, 240, 58, 43), }; -DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops); +DEFINE_DRM_GEM_DMA_FOPS(mi0283qt_fops); static const struct drm_driver mi0283qt_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &mi0283qt_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "mi0283qt", .desc = "Multi-Inno MI0283QT", diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c index c759ff9c2c87..a76fefa8adbc 100644 --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c @@ -18,7 +18,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> #include <drm/drm_modes.h> @@ -217,12 +217,12 @@ static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = { .update = mipi_dbi_pipe_update, }; -DEFINE_DRM_GEM_CMA_FOPS(panel_mipi_dbi_fops); +DEFINE_DRM_GEM_DMA_FOPS(panel_mipi_dbi_fops); static const struct drm_driver panel_mipi_dbi_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &panel_mipi_dbi_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "panel-mipi-dbi", .desc = "MIPI DBI compatible display panel", diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 6d3b5b3cb955..4cd24b54ac74 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -30,7 +30,7 @@ #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_modes.h> @@ -511,7 +511,7 @@ static void repaper_get_temperature(struct repaper_epd *epd) static int repaper_fb_dirty(struct drm_framebuffer *fb) { - struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct repaper_epd *epd = drm_to_epd(fb->dev); struct drm_rect clip; int idx, ret = 0; @@ -541,7 +541,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) if (ret) goto out_free; - drm_fb_xrgb8888_to_mono(buf, 0, cma_obj->vaddr, fb, &clip); + drm_fb_xrgb8888_to_mono(buf, 0, dma_obj->vaddr, fb, &clip); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); @@ -903,12 +903,12 @@ static const struct drm_display_mode repaper_e2271cs021_mode = { static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00 }; -DEFINE_DRM_GEM_CMA_FOPS(repaper_fops); +DEFINE_DRM_GEM_DMA_FOPS(repaper_fops); static const struct drm_driver repaper_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &repaper_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .name = "repaper", .desc = "Pervasive Displays RePaper e-ink panels", .date = "20170405", diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index b1584b362c79..94f55fac4295 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -20,7 +20,7 @@ #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> @@ -92,8 +92,8 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_rect *clip) { - struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); - void *src = cma_obj->vaddr; + struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + void *src = dma_obj->vaddr; int ret = 0; ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); @@ -269,12 +269,12 @@ static const struct drm_display_mode st7586_mode = { DRM_SIMPLE_MODE(178, 128, 37, 27), }; -DEFINE_DRM_GEM_CMA_FOPS(st7586_fops); +DEFINE_DRM_GEM_DMA_FOPS(st7586_fops); static const struct drm_driver st7586_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &st7586_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "st7586", .desc = "Sitronix ST7586", diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index e0f02d367d88..d2042a0f02dd 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -20,7 +20,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mipi_dbi.h> @@ -151,12 +151,12 @@ static const struct st7735r_cfg rh128128t_cfg = { .rgb = true, }; -DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops); +DEFINE_DRM_GEM_DMA_FOPS(st7735r_fops); static const struct drm_driver st7735r_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &st7735r_fops, - DRM_GEM_CMA_DRIVER_OPS_VMAP, + DRM_GEM_DMA_DRIVER_OPS_VMAP, .debugfs_init = mipi_dbi_debugfs_init, .name = "st7735r", .desc = "Sitronix ST7735R", diff --git a/drivers/gpu/drm/tve200/Kconfig b/drivers/gpu/drm/tve200/Kconfig index 47a7dbe6c114..11e865be81c6 100644 --- a/drivers/gpu/drm/tve200/Kconfig +++ b/drivers/gpu/drm/tve200/Kconfig @@ -8,7 +8,7 @@ config DRM_TVE200 select DRM_BRIDGE select DRM_PANEL_BRIDGE select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help Choose this option for DRM support for the Faraday TV Encoder diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index 6647aab8a25e..37bdd976ae59 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -19,7 +19,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_panel.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index 86ebfe626cd0..79d790ae1670 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -40,7 +40,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_of.h> @@ -134,7 +134,7 @@ finish: return ret; } -DEFINE_DRM_GEM_CMA_FOPS(drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(drm_fops); static const struct drm_driver tve200_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, @@ -146,7 +146,7 @@ static const struct drm_driver tve200_drm_driver = { .major = 1, .minor = 0, .patchlevel = 0, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, }; static int tve200_probe(struct platform_device *pdev) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 725a252e837b..b8980440d137 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -313,7 +313,7 @@ v3d_lookup_bos(struct drm_device *dev, } job->bo = kvmalloc_array(job->bo_count, - sizeof(struct drm_gem_cma_object *), + sizeof(struct drm_gem_dma_object *), GFP_KERNEL | __GFP_ZERO); if (!job->bo) { DRM_DEBUG("Failed to allocate validated BO pointers\n"); @@ -1092,7 +1092,7 @@ v3d_gem_init(struct drm_device *dev) if (!v3d->pt) { drm_mm_takedown(&v3d->mm); dev_err(v3d->drm.dev, - "Failed to allocate page tables. Please ensure you have CMA enabled.\n"); + "Failed to allocate page tables. Please ensure you have DMA enabled.\n"); return -ENOMEM; } diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index b0f3117102ca..246305d17a52 100644 --- a/drivers/gpu/drm/vc4/Kconfig +++ b/drivers/gpu/drm/vc4/Kconfig @@ -12,7 +12,7 @@ config DRM_VC4 select DRM_DISPLAY_HDMI_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_PANEL_BRIDGE select SND_PCM select SND_PCM_ELD diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 2ccf96b764db..07f57910c9e8 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -8,10 +8,10 @@ * * The VC4 GPU architecture (both scanout and rendering) has direct * access to system memory with no MMU in between. To support it, we - * use the GEM CMA helper functions to allocate contiguous ranges of + * use the GEM DMA helper functions to allocate contiguous ranges of * physical memory for our BOs. * - * Since the CMA allocator is very slow, we keep a cache of recently + * Since the DMA allocator is very slow, we keep a cache of recently * freed BOs around so that the kernel's allocation of objects for 3D * rendering can return quickly. */ @@ -179,7 +179,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo) bo->validated_shader = NULL; } - drm_gem_cma_free(&bo->base); + drm_gem_dma_free(&bo->base); } static void vc4_bo_remove_from_cache(struct vc4_bo *bo) @@ -387,7 +387,7 @@ out: * @dev: DRM device * @size: Size in bytes of the memory the object will reference * - * This lets the CMA helpers allocate object structs for us, and keep + * This lets the DMA helpers allocate object structs for us, and keep * our BO stats correct. */ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) @@ -426,7 +426,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, { size_t size = roundup(unaligned_size, PAGE_SIZE); struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct vc4_bo *bo; if (WARN_ON_ONCE(vc4->is_vc5)) @@ -443,39 +443,39 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, return bo; } - cma_obj = drm_gem_cma_create(dev, size); - if (IS_ERR(cma_obj)) { + dma_obj = drm_gem_dma_create(dev, size); + if (IS_ERR(dma_obj)) { /* - * If we've run out of CMA memory, kill the cache of - * CMA allocations we've got laying around and try again. + * If we've run out of DMA memory, kill the cache of + * DMA allocations we've got laying around and try again. */ vc4_bo_cache_purge(dev); - cma_obj = drm_gem_cma_create(dev, size); + dma_obj = drm_gem_dma_create(dev, size); } - if (IS_ERR(cma_obj)) { + if (IS_ERR(dma_obj)) { /* - * Still not enough CMA memory, purge the userspace BO + * Still not enough DMA memory, purge the userspace BO * cache and retry. * This is sub-optimal since we purge the whole userspace * BO cache which forces user that want to re-use the BO to * restore its initial content. * Ideally, we should purge entries one by one and retry - * after each to see if CMA allocation succeeds. Or even + * after each to see if DMA allocation succeeds. Or even * better, try to find an entry with at least the same * size. */ vc4_bo_userspace_cache_purge(dev); - cma_obj = drm_gem_cma_create(dev, size); + dma_obj = drm_gem_dma_create(dev, size); } - if (IS_ERR(cma_obj)) { + if (IS_ERR(dma_obj)) { struct drm_printer p = drm_info_printer(vc4->base.dev); - DRM_ERROR("Failed to allocate from CMA:\n"); + DRM_ERROR("Failed to allocate from GEM DMA helper:\n"); vc4_bo_stats_print(&p, vc4); return ERR_PTR(-ENOMEM); } - bo = to_vc4_bo(&cma_obj->base); + bo = to_vc4_bo(&dma_obj->base); /* By default, BOs do not support the MADV ioctl. This will be enabled * only on BOs that are exposed to userspace (V3D, V3D_SHADER and DUMB @@ -484,7 +484,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, bo->madv = __VC4_MADV_NOTSUPP; mutex_lock(&vc4->bo_lock); - vc4_bo_set_label(&cma_obj->base, type); + vc4_bo_set_label(&dma_obj->base, type); mutex_unlock(&vc4->bo_lock); return bo; @@ -569,7 +569,7 @@ static void vc4_free_object(struct drm_gem_object *gem_bo) goto out; } - /* If this object was partially constructed but CMA allocation + /* If this object was partially constructed but DMA allocation * had failed, just free it. Can also happen when the BO has been * purged. */ @@ -747,7 +747,7 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct return -EINVAL; } - return drm_gem_cma_mmap(&bo->base, vma); + return drm_gem_dma_mmap(&bo->base, vma); } static const struct vm_operations_struct vc4_vm_ops = { @@ -759,8 +759,8 @@ static const struct vm_operations_struct vc4_vm_ops = { static const struct drm_gem_object_funcs vc4_gem_object_funcs = { .free = vc4_free_object, .export = vc4_prime_export, - .get_sg_table = drm_gem_cma_object_get_sg_table, - .vmap = drm_gem_cma_object_vmap, + .get_sg_table = drm_gem_dma_object_get_sg_table, + .vmap = drm_gem_dma_object_vmap, .mmap = vc4_gem_object_mmap, .vm_ops = &vc4_vm_ops, }; diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index f85788401707..2def6e2ad6f0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -823,9 +823,9 @@ static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) struct vc4_bo *bo = NULL; if (flip_state->old_fb) { - struct drm_gem_cma_object *cma_bo = + struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(flip_state->old_fb, 0); - bo = to_vc4_bo(&cma_bo->base); + bo = to_vc4_bo(&dma_bo->base); } vc4_async_page_flip_complete(flip_state); @@ -857,19 +857,19 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, struct vc4_async_flip_state *flip_state) { struct drm_framebuffer *fb = flip_state->fb; - struct drm_gem_cma_object *cma_bo = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0); struct vc4_dev *vc4 = to_vc4_dev(dev); struct dma_fence *fence; int ret; if (!vc4->is_vc5) { - struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); return vc4_queue_seqno_cb(dev, &flip_state->cb.seqno, bo->seqno, vc4_async_page_flip_seqno_complete); } - ret = dma_resv_get_singleton(cma_bo->base.resv, DMA_RESV_USAGE_READ, &fence); + ret = dma_resv_get_singleton(dma_bo->base.resv, DMA_RESV_USAGE_READ, &fence); if (ret) return ret; @@ -945,8 +945,8 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_gem_cma_object *cma_bo = drm_fb_dma_get_gem_obj(fb, 0); - struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); + struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0); + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); int ret; if (WARN_ON_ONCE(vc4->is_vc5)) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index d33baf2667dd..ffbbb454c9e8 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -85,7 +85,7 @@ static int vc5_dumb_create(struct drm_file *file_priv, if (ret) return ret; - return drm_gem_cma_dumb_create_internal(file_priv, dev, args); + return drm_gem_dma_dumb_create_internal(file_priv, dev, args); } static int vc4_get_param_ioctl(struct drm_device *dev, void *data, @@ -211,7 +211,7 @@ static const struct drm_driver vc4_drm_driver = { .gem_create_object = vc4_create_object, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(vc4_bo_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc4_bo_dumb_create), .ioctls = vc4_drm_ioctls, .num_ioctls = ARRAY_SIZE(vc4_drm_ioctls), @@ -234,7 +234,7 @@ static const struct drm_driver vc5_drm_driver = { .debugfs_init = vc4_debugfs_init, #endif - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(vc5_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc5_dumb_create), .fops = &vc4_drm_fops, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 1649350b9efd..418a8242691f 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -14,7 +14,7 @@ #include <drm/drm_debugfs.h> #include <drm/drm_device.h> #include <drm/drm_encoder.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mm.h> #include <drm/drm_modeset_lock.h> @@ -239,7 +239,7 @@ to_vc4_dev(struct drm_device *dev) } struct vc4_bo { - struct drm_gem_cma_object base; + struct drm_gem_dma_object base; /* seqno of the last job to render using this BO. */ uint64_t seqno; @@ -288,7 +288,7 @@ struct vc4_bo { static inline struct vc4_bo * to_vc4_bo(struct drm_gem_object *bo) { - return container_of(to_drm_gem_cma_obj(bo), struct vc4_bo, base); + return container_of(to_drm_gem_dma_obj(bo), struct vc4_bo, base); } struct vc4_fence { @@ -602,14 +602,14 @@ struct vc4_exec_info { /* This is the array of BOs that were looked up at the start of exec. * Command validation will use indices into this array. */ - struct drm_gem_cma_object **bo; + struct drm_gem_dma_object **bo; uint32_t bo_count; /* List of BOs that are being written by the RCL. Other than * the binner temporary storage, this is all the BOs written * by the job. */ - struct drm_gem_cma_object *rcl_write_bo[4]; + struct drm_gem_dma_object *rcl_write_bo[4]; uint32_t rcl_write_bo_count; /* Pointers for our position in vc4->job_list */ @@ -628,7 +628,7 @@ struct vc4_exec_info { /* This is the BO where we store the validated command lists, shader * records, and uniforms. */ - struct drm_gem_cma_object *exec_bo; + struct drm_gem_dma_object *exec_bo; /** * This tracks the per-shader-record state (packet 64) that @@ -989,19 +989,19 @@ vc4_validate_bin_cl(struct drm_device *dev, int vc4_validate_shader_recs(struct drm_device *dev, struct vc4_exec_info *exec); -struct drm_gem_cma_object *vc4_use_bo(struct vc4_exec_info *exec, +struct drm_gem_dma_object *vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex); int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec); bool vc4_check_tex_size(struct vc4_exec_info *exec, - struct drm_gem_cma_object *fbo, + struct drm_gem_dma_object *fbo, uint32_t offset, uint8_t tiling_format, uint32_t width, uint32_t height, uint8_t cpp); /* vc4_validate_shader.c */ struct vc4_validated_shader_info * -vc4_validate_shader(struct drm_gem_cma_object *shader_obj); +vc4_validate_shader(struct drm_gem_dma_object *shader_obj); /* vc4_perfmon.c */ void vc4_perfmon_get(struct vc4_perfmon *perfmon); diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 7acb43972e69..56a0af281b92 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -764,7 +764,7 @@ vc4_cl_lookup_bos(struct drm_device *dev, } exec->bo = kvmalloc_array(exec->bo_count, - sizeof(struct drm_gem_cma_object *), + sizeof(struct drm_gem_dma_object *), GFP_KERNEL | __GFP_ZERO); if (!exec->bo) { DRM_ERROR("Failed to allocate validated BO pointers\n"); @@ -797,7 +797,7 @@ vc4_cl_lookup_bos(struct drm_device *dev, } drm_gem_object_get(bo); - exec->bo[i] = (struct drm_gem_cma_object *)bo; + exec->bo[i] = (struct drm_gem_dma_object *)bo; } spin_unlock(&file_priv->table_lock); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 51e0e8aa2135..b76b0e602c81 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -339,7 +339,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); int num_planes = fb->format->num_planes; struct drm_crtc_state *crtc_state; u32 h_subsample = fb->format->hsub; @@ -1243,7 +1243,7 @@ u32 vc4_plane_dlist_size(const struct drm_plane_state *state) void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); - struct drm_gem_cma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); uint32_t addr; /* We're skipping the address adjustment for negative origin, diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c index f6b7dc3df08c..c8a92023238c 100644 --- a/drivers/gpu/drm/vc4/vc4_render_cl.c +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c @@ -40,14 +40,14 @@ #include "vc4_packet.h" struct vc4_rcl_setup { - struct drm_gem_cma_object *color_read; - struct drm_gem_cma_object *color_write; - struct drm_gem_cma_object *zs_read; - struct drm_gem_cma_object *zs_write; - struct drm_gem_cma_object *msaa_color_write; - struct drm_gem_cma_object *msaa_zs_write; + struct drm_gem_dma_object *color_read; + struct drm_gem_dma_object *color_write; + struct drm_gem_dma_object *zs_read; + struct drm_gem_dma_object *zs_write; + struct drm_gem_dma_object *msaa_color_write; + struct drm_gem_dma_object *msaa_zs_write; - struct drm_gem_cma_object *rcl; + struct drm_gem_dma_object *rcl; u32 next_offset; u32 next_write_bo_index; @@ -97,7 +97,7 @@ static void vc4_store_before_load(struct vc4_rcl_setup *setup) * coordinates packet, and instead just store to the address given. */ static uint32_t vc4_full_res_offset(struct vc4_exec_info *exec, - struct drm_gem_cma_object *bo, + struct drm_gem_dma_object *bo, struct drm_vc4_submit_rcl_surface *surf, uint8_t x, uint8_t y) { @@ -381,7 +381,7 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, } static int vc4_full_res_bounds_check(struct vc4_exec_info *exec, - struct drm_gem_cma_object *obj, + struct drm_gem_dma_object *obj, struct drm_vc4_submit_rcl_surface *surf) { struct drm_vc4_submit_cl *args = exec->args; @@ -407,7 +407,7 @@ static int vc4_full_res_bounds_check(struct vc4_exec_info *exec, } static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec, - struct drm_gem_cma_object **obj, + struct drm_gem_dma_object **obj, struct drm_vc4_submit_rcl_surface *surf) { if (surf->flags != 0 || surf->bits != 0) { @@ -433,7 +433,7 @@ static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec, } static int vc4_rcl_surface_setup(struct vc4_exec_info *exec, - struct drm_gem_cma_object **obj, + struct drm_gem_dma_object **obj, struct drm_vc4_submit_rcl_surface *surf, bool is_write) { @@ -533,7 +533,7 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec, static int vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec, struct vc4_rcl_setup *setup, - struct drm_gem_cma_object **obj, + struct drm_gem_dma_object **obj, struct drm_vc4_submit_rcl_surface *surf) { uint8_t tiling = VC4_GET_FIELD(surf->bits, diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index af48ae68f213..811bc7d9b90c 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -280,7 +280,7 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, conn); struct vc4_txp *txp = connector_to_vc4_txp(conn); - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; struct drm_display_mode *mode; struct drm_framebuffer *fb; u32 ctrl; diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 40f04157ea39..6222c884dcbb 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -231,7 +231,7 @@ try_again: * if it doesn't fit within the buffer that we allocated up front. * However, it turns out that 16MB is "enough for anybody", and * real-world applications run into allocation failures from the - * overall CMA pool before they make scenes complicated enough to run + * overall DMA pool before they make scenes complicated enough to run * out of bin space. */ static int bin_bo_alloc(struct vc4_dev *vc4) @@ -261,7 +261,7 @@ static int bin_bo_alloc(struct vc4_dev *vc4) dev_err(&v3d->pdev->dev, "Failed to allocate memory for tile binning: " - "%d. You may need to enable CMA or give it " + "%d. You may need to enable DMA or give it " "more memory.", ret); break; diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index 2feba55bcef7..d5dc6b51ec69 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -102,11 +102,11 @@ size_is_lt(uint32_t width, uint32_t height, int cpp) height <= 4 * utile_height(cpp)); } -struct drm_gem_cma_object * +struct drm_gem_dma_object * vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex) { struct vc4_dev *vc4 = exec->dev; - struct drm_gem_cma_object *obj; + struct drm_gem_dma_object *obj; struct vc4_bo *bo; if (WARN_ON_ONCE(vc4->is_vc5)) @@ -129,7 +129,7 @@ vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex) return obj; } -static struct drm_gem_cma_object * +static struct drm_gem_dma_object * vc4_use_handle(struct vc4_exec_info *exec, uint32_t gem_handles_packet_index) { return vc4_use_bo(exec, exec->bo_index[gem_handles_packet_index]); @@ -160,7 +160,7 @@ gl_shader_rec_size(uint32_t pointer_bits) } bool -vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo, +vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_dma_object *fbo, uint32_t offset, uint8_t tiling_format, uint32_t width, uint32_t height, uint8_t cpp) { @@ -263,7 +263,7 @@ validate_increment_semaphore(VALIDATE_ARGS) static int validate_indexed_prim_list(VALIDATE_ARGS) { - struct drm_gem_cma_object *ib; + struct drm_gem_dma_object *ib; uint32_t length = *(uint32_t *)(untrusted + 1); uint32_t offset = *(uint32_t *)(untrusted + 5); uint32_t max_index = *(uint32_t *)(untrusted + 9); @@ -575,7 +575,7 @@ reloc_tex(struct vc4_exec_info *exec, struct vc4_texture_sample_info *sample, uint32_t texture_handle_index, bool is_cs) { - struct drm_gem_cma_object *tex; + struct drm_gem_dma_object *tex; uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]); uint32_t p1 = *(uint32_t *)(uniform_data_u + sample->p_offset[1]); uint32_t p2 = (sample->p_offset[2] != ~0 ? @@ -765,7 +765,7 @@ validate_gl_shader_rec(struct drm_device *dev, 28, /* cs */ }; uint32_t shader_reloc_count = ARRAY_SIZE(shader_reloc_offsets); - struct drm_gem_cma_object *bo[ARRAY_SIZE(shader_reloc_offsets) + 8]; + struct drm_gem_dma_object *bo[ARRAY_SIZE(shader_reloc_offsets) + 8]; uint32_t nr_attributes, nr_relocs, packet_size; int i; @@ -896,7 +896,7 @@ validate_gl_shader_rec(struct drm_device *dev, } for (i = 0; i < nr_attributes; i++) { - struct drm_gem_cma_object *vbo = + struct drm_gem_dma_object *vbo = bo[ARRAY_SIZE(shader_reloc_offsets) + i]; uint32_t o = 36 + i * 8; uint32_t offset = *(uint32_t *)(pkt_u + o + 0); diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c index e315aeb5fef5..9745f8810eca 100644 --- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c +++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c @@ -776,7 +776,7 @@ vc4_handle_branch_target(struct vc4_shader_validation_state *validation_state) } struct vc4_validated_shader_info * -vc4_validate_shader(struct drm_gem_cma_object *shader_obj) +vc4_validate_shader(struct drm_gem_dma_object *shader_obj) { struct vc4_dev *vc4 = to_vc4_dev(shader_obj->base.dev); bool found_shader_end = false; diff --git a/drivers/gpu/drm/xlnx/Kconfig b/drivers/gpu/drm/xlnx/Kconfig index f9cf93c9e7e3..68ee897de9d7 100644 --- a/drivers/gpu/drm/xlnx/Kconfig +++ b/drivers/gpu/drm/xlnx/Kconfig @@ -8,7 +8,7 @@ config DRM_ZYNQMP_DPSUB select DMA_ENGINE select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select GENERIC_PHY help diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c index 824b510e337b..1de2d927c32b 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c @@ -21,7 +21,7 @@ #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_mode_config.h> @@ -47,7 +47,7 @@ static int zynqmp_dpsub_dumb_create(struct drm_file *file_priv, /* Enforce the alignment constraints of the DMA engine. */ args->pitch = ALIGN(pitch, dpsub->dma_align); - return drm_gem_cma_dumb_create_internal(file_priv, drm, args); + return drm_gem_dma_dumb_create_internal(file_priv, drm, args); } static struct drm_framebuffer * @@ -75,13 +75,13 @@ static const struct drm_mode_config_funcs zynqmp_dpsub_mode_config_funcs = { * DRM/KMS Driver */ -DEFINE_DRM_GEM_CMA_FOPS(zynqmp_dpsub_drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(zynqmp_dpsub_drm_fops); static const struct drm_driver zynqmp_dpsub_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(zynqmp_dpsub_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(zynqmp_dpsub_dumb_create), .fops = &zynqmp_dpsub_drm_fops, diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h index 05f657363b30..d5e036c57801 100644 --- a/include/drm/drm_fb_dma_helper.h +++ b/include/drm/drm_fb_dma_helper.h @@ -8,7 +8,7 @@ struct drm_device; struct drm_framebuffer; struct drm_plane_state; -struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, +struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane); dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 87cffc9efa85..58a18a17c67e 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -217,7 +217,7 @@ struct drm_gem_object { * * SHMEM file node used as backing storage for swappable buffer objects. * GEM also supports driver private objects with driver-specific backing - * storage (contiguous CMA memory, special reserved blocks). In this + * storage (contiguous DMA memory, special reserved blocks). In this * case @filp is NULL. */ struct file *filp; diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_dma_helper.h similarity index 53% rename from include/drm/drm_gem_cma_helper.h rename to include/drm/drm_gem_dma_helper.h index fbda4ce5d5fb..82805069b37a 100644 --- a/include/drm/drm_gem_cma_helper.h +++ b/include/drm/drm_gem_dma_helper.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __DRM_GEM_CMA_HELPER_H__ -#define __DRM_GEM_CMA_HELPER_H__ +#ifndef __DRM_GEM_DMA_HELPER_H__ +#define __DRM_GEM_DMA_HELPER_H__ #include <drm/drm_file.h> #include <drm/drm_ioctl.h> @@ -9,128 +9,128 @@ struct drm_mode_create_dumb; /** - * struct drm_gem_cma_object - GEM object backed by CMA memory allocations + * struct drm_gem_dma_object - GEM object backed by DMA memory allocations * @base: base GEM object - * @paddr: physical address of the backing memory + * @paddr: DMA address of the backing memory * @sgt: scatter/gather table for imported PRIME buffers. The table can have * more than one entry but they are guaranteed to have contiguous * DMA addresses. * @vaddr: kernel virtual address of the backing memory * @map_noncoherent: if true, the GEM object is backed by non-coherent memory */ -struct drm_gem_cma_object { +struct drm_gem_dma_object { struct drm_gem_object base; dma_addr_t paddr; struct sg_table *sgt; - /* For objects with DMA memory allocated by GEM CMA */ + /* For objects with DMA memory allocated by GEM DMA */ void *vaddr; bool map_noncoherent; }; -#define to_drm_gem_cma_obj(gem_obj) \ - container_of(gem_obj, struct drm_gem_cma_object, base) +#define to_drm_gem_dma_obj(gem_obj) \ + container_of(gem_obj, struct drm_gem_dma_object, base) -struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, +struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm, size_t size); -void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj); -void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj, +void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj); +void drm_gem_dma_print_info(const struct drm_gem_dma_object *dma_obj, struct drm_printer *p, unsigned int indent); -struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj); -int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj, +struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj); +int drm_gem_dma_vmap(struct drm_gem_dma_object *dma_obj, struct iosys_map *map); -int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma); +int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct *vma); -extern const struct vm_operations_struct drm_gem_cma_vm_ops; +extern const struct vm_operations_struct drm_gem_dma_vm_ops; /* * GEM object functions */ /** - * drm_gem_cma_object_free - GEM object function for drm_gem_cma_free() + * drm_gem_dma_object_free - GEM object function for drm_gem_dma_free() * @obj: GEM object to free * - * This function wraps drm_gem_cma_free_object(). Drivers that employ the CMA helpers + * This function wraps drm_gem_dma_free_object(). Drivers that employ the DMA helpers * should use it as their &drm_gem_object_funcs.free handler. */ -static inline void drm_gem_cma_object_free(struct drm_gem_object *obj) +static inline void drm_gem_dma_object_free(struct drm_gem_object *obj) { - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); - drm_gem_cma_free(cma_obj); + drm_gem_dma_free(dma_obj); } /** - * drm_gem_cma_object_print_info() - Print &drm_gem_cma_object info for debugfs + * drm_gem_dma_object_print_info() - Print &drm_gem_dma_object info for debugfs * @p: DRM printer * @indent: Tab indentation level * @obj: GEM object * - * This function wraps drm_gem_cma_print_info(). Drivers that employ the CMA helpers + * This function wraps drm_gem_dma_print_info(). Drivers that employ the DMA helpers * should use this function as their &drm_gem_object_funcs.print_info handler. */ -static inline void drm_gem_cma_object_print_info(struct drm_printer *p, unsigned int indent, +static inline void drm_gem_dma_object_print_info(struct drm_printer *p, unsigned int indent, const struct drm_gem_object *obj) { - const struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + const struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); - drm_gem_cma_print_info(cma_obj, p, indent); + drm_gem_dma_print_info(dma_obj, p, indent); } /** - * drm_gem_cma_object_get_sg_table - GEM object function for drm_gem_cma_get_sg_table() + * drm_gem_dma_object_get_sg_table - GEM object function for drm_gem_dma_get_sg_table() * @obj: GEM object * - * This function wraps drm_gem_cma_get_sg_table(). Drivers that employ the CMA helpers should + * This function wraps drm_gem_dma_get_sg_table(). Drivers that employ the DMA helpers should * use it as their &drm_gem_object_funcs.get_sg_table handler. * * Returns: * A pointer to the scatter/gather table of pinned pages or NULL on failure. */ -static inline struct sg_table *drm_gem_cma_object_get_sg_table(struct drm_gem_object *obj) +static inline struct sg_table *drm_gem_dma_object_get_sg_table(struct drm_gem_object *obj) { - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); - return drm_gem_cma_get_sg_table(cma_obj); + return drm_gem_dma_get_sg_table(dma_obj); } /* - * drm_gem_cma_object_vmap - GEM object function for drm_gem_cma_vmap() + * drm_gem_dma_object_vmap - GEM object function for drm_gem_dma_vmap() * @obj: GEM object - * @map: Returns the kernel virtual address of the CMA GEM object's backing store. + * @map: Returns the kernel virtual address of the DMA GEM object's backing store. * - * This function wraps drm_gem_cma_vmap(). Drivers that employ the CMA helpers should + * This function wraps drm_gem_dma_vmap(). Drivers that employ the DMA helpers should * use it as their &drm_gem_object_funcs.vmap handler. * * Returns: * 0 on success or a negative error code on failure. */ -static inline int drm_gem_cma_object_vmap(struct drm_gem_object *obj, +static inline int drm_gem_dma_object_vmap(struct drm_gem_object *obj, struct iosys_map *map) { - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); - return drm_gem_cma_vmap(cma_obj, map); + return drm_gem_dma_vmap(dma_obj, map); } /** - * drm_gem_cma_object_mmap - GEM object function for drm_gem_cma_mmap() + * drm_gem_dma_object_mmap - GEM object function for drm_gem_dma_mmap() * @obj: GEM object * @vma: VMA for the area to be mapped * - * This function wraps drm_gem_cma_mmap(). Drivers that employ the cma helpers should + * This function wraps drm_gem_dma_mmap(). Drivers that employ the dma helpers should * use it as their &drm_gem_object_funcs.mmap handler. * * Returns: * 0 on success or a negative error code on failure. */ -static inline int drm_gem_cma_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +static inline int drm_gem_dma_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) { - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj); - return drm_gem_cma_mmap(cma_obj, vma); + return drm_gem_dma_mmap(dma_obj, vma); } /* @@ -138,57 +138,57 @@ static inline int drm_gem_cma_object_mmap(struct drm_gem_object *obj, struct vm_ */ /* create memory region for DRM framebuffer */ -int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv, +int drm_gem_dma_dumb_create_internal(struct drm_file *file_priv, struct drm_device *drm, struct drm_mode_create_dumb *args); /* create memory region for DRM framebuffer */ -int drm_gem_cma_dumb_create(struct drm_file *file_priv, +int drm_gem_dma_dumb_create(struct drm_file *file_priv, struct drm_device *drm, struct drm_mode_create_dumb *args); struct drm_gem_object * -drm_gem_cma_prime_import_sg_table(struct drm_device *dev, +drm_gem_dma_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); /** - * DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE - CMA GEM driver operations + * DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE - DMA GEM driver operations * @dumb_create_func: callback function for .dumb_create * * This macro provides a shortcut for setting the default GEM operations in the * &drm_driver structure. * - * This macro is a variant of DRM_GEM_CMA_DRIVER_OPS for drivers that + * This macro is a variant of DRM_GEM_DMA_DRIVER_OPS for drivers that * override the default implementation of &struct rm_driver.dumb_create. Use - * DRM_GEM_CMA_DRIVER_OPS if possible. Drivers that require a virtual address + * DRM_GEM_DMA_DRIVER_OPS if possible. Drivers that require a virtual address * on imported buffers should use - * DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead. + * DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead. */ -#define DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(dumb_create_func) \ +#define DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(dumb_create_func) \ .dumb_create = (dumb_create_func), \ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, \ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, \ - .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, \ + .gem_prime_import_sg_table = drm_gem_dma_prime_import_sg_table, \ .gem_prime_mmap = drm_gem_prime_mmap /** - * DRM_GEM_CMA_DRIVER_OPS - CMA GEM driver operations + * DRM_GEM_DMA_DRIVER_OPS - DMA GEM driver operations * * This macro provides a shortcut for setting the default GEM operations in the * &drm_driver structure. * * Drivers that come with their own implementation of * &struct drm_driver.dumb_create should use - * DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE() instead. Use - * DRM_GEM_CMA_DRIVER_OPS if possible. Drivers that require a virtual address - * on imported buffers should use DRM_GEM_CMA_DRIVER_OPS_VMAP instead. + * DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE() instead. Use + * DRM_GEM_DMA_DRIVER_OPS if possible. Drivers that require a virtual address + * on imported buffers should use DRM_GEM_DMA_DRIVER_OPS_VMAP instead. */ -#define DRM_GEM_CMA_DRIVER_OPS \ - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_gem_cma_dumb_create) +#define DRM_GEM_DMA_DRIVER_OPS \ + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_gem_dma_dumb_create) /** - * DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE - CMA GEM driver operations + * DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE - DMA GEM driver operations * ensuring a virtual address * on the buffer * @dumb_create_func: callback function for .dumb_create @@ -197,21 +197,21 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, * &drm_driver structure for drivers that need the virtual address also on * imported buffers. * - * This macro is a variant of DRM_GEM_CMA_DRIVER_OPS_VMAP for drivers that + * This macro is a variant of DRM_GEM_DMA_DRIVER_OPS_VMAP for drivers that * override the default implementation of &struct drm_driver.dumb_create. Use - * DRM_GEM_CMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a + * DRM_GEM_DMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a * virtual address on imported buffers should use - * DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE() instead. + * DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE() instead. */ -#define DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(dumb_create_func) \ +#define DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(dumb_create_func) \ .dumb_create = dumb_create_func, \ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, \ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, \ - .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table_vmap, \ + .gem_prime_import_sg_table = drm_gem_dma_prime_import_sg_table_vmap, \ .gem_prime_mmap = drm_gem_prime_mmap /** - * DRM_GEM_CMA_DRIVER_OPS_VMAP - CMA GEM driver operations ensuring a virtual + * DRM_GEM_DMA_DRIVER_OPS_VMAP - DMA GEM driver operations ensuring a virtual * address on the buffer * * This macro provides a shortcut for setting the default GEM operations in the @@ -220,16 +220,16 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, * * Drivers that come with their own implementation of * &struct drm_driver.dumb_create should use - * DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead. Use - * DRM_GEM_CMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a - * virtual address on imported buffers should use DRM_GEM_CMA_DRIVER_OPS + * DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead. Use + * DRM_GEM_DMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a + * virtual address on imported buffers should use DRM_GEM_DMA_DRIVER_OPS * instead. */ -#define DRM_GEM_CMA_DRIVER_OPS_VMAP \ - DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(drm_gem_cma_dumb_create) +#define DRM_GEM_DMA_DRIVER_OPS_VMAP \ + DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(drm_gem_dma_dumb_create) struct drm_gem_object * -drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *drm, +drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *drm, struct dma_buf_attachment *attach, struct sg_table *sgt); @@ -238,22 +238,22 @@ drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *drm, */ #ifndef CONFIG_MMU -unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, +unsigned long drm_gem_dma_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); -#define DRM_GEM_CMA_UNMAPPED_AREA_FOPS \ - .get_unmapped_area = drm_gem_cma_get_unmapped_area, +#define DRM_GEM_DMA_UNMAPPED_AREA_FOPS \ + .get_unmapped_area = drm_gem_dma_get_unmapped_area, #else -#define DRM_GEM_CMA_UNMAPPED_AREA_FOPS +#define DRM_GEM_DMA_UNMAPPED_AREA_FOPS #endif /** - * DEFINE_DRM_GEM_CMA_FOPS() - macro to generate file operations for CMA drivers + * DEFINE_DRM_GEM_DMA_FOPS() - macro to generate file operations for DMA drivers * @name: name for the generated structure * - * This macro autogenerates a suitable &struct file_operations for CMA based + * This macro autogenerates a suitable &struct file_operations for DMA based * drivers, which can be assigned to &drm_driver.fops. Note that this structure * cannot be shared between drivers, because it contains a reference to the * current module using THIS_MODULE. @@ -262,7 +262,7 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, * non-static version of this you're probably doing it wrong and will break the * THIS_MODULE reference by accident. */ -#define DEFINE_DRM_GEM_CMA_FOPS(name) \ +#define DEFINE_DRM_GEM_DMA_FOPS(name) \ static const struct file_operations name = {\ .owner = THIS_MODULE,\ .open = drm_open,\ @@ -273,7 +273,7 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, .read = drm_read,\ .llseek = noop_llseek,\ .mmap = drm_gem_mmap,\ - DRM_GEM_CMA_UNMAPPED_AREA_FOPS \ + DRM_GEM_DMA_UNMAPPED_AREA_FOPS \ } -#endif /* __DRM_GEM_CMA_HELPER_H__ */ +#endif /* __DRM_GEM_DMA_HELPER_H__ */ From 8c30eecc6769bee1e3acb485ad5f086a4d8a04b6 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Tue, 2 Aug 2022 02:04:04 +0200 Subject: [PATCH 240/396] drm/gem: rename struct drm_gem_dma_object.{paddr => dma_addr} The field paddr of struct drm_gem_dma_object holds a DMA address, which might actually be a physical address. However, depending on the platform, it can also be a bus address or a virtual address managed by an IOMMU. Hence, rename the field to dma_addr, which is more applicable. In order to do this renaming the following coccinelle script was used: ``` @@ struct drm_gem_dma_object *gem; @@ - gem->paddr + gem->dma_addr @@ struct drm_gem_dma_object gem; @@ - gem.paddr + gem.dma_addr @exists@ typedef dma_addr_t; symbol paddr; @@ dma_addr_t paddr; <... - paddr + dma_addr ...> @@ symbol paddr; @@ dma_addr_t - paddr + dma_addr ; ``` This patch is compile-time tested with: ``` make ARCH={x86_64,arm,arm64} allyesconfig make ARCH={x86_64,arm,arm64} drivers/gpu/drm` ``` Acked-by: Sam Ravnborg <sam@ravnborg.org> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220802000405.949236-5-dakr@redhat.com --- .../arm/display/komeda/komeda_framebuffer.c | 4 +-- drivers/gpu/drm/arm/malidp_mw.c | 2 +- drivers/gpu/drm/arm/malidp_planes.c | 12 ++++---- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 2 +- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 2 +- drivers/gpu/drm/drm_fb_dma_helper.c | 10 +++---- drivers/gpu/drm/drm_gem_dma_helper.c | 23 +++++++------- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 2 +- .../gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 4 +-- drivers/gpu/drm/imx/dcss/dcss-plane.c | 6 ++-- drivers/gpu/drm/imx/ipuv3-plane.c | 6 ++-- drivers/gpu/drm/meson/meson_overlay.c | 6 ++-- drivers/gpu/drm/meson/meson_plane.c | 2 +- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 30 +++++++++---------- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 2 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 4 +-- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 4 +-- drivers/gpu/drm/sprd/sprd_dpu.c | 2 +- drivers/gpu/drm/sti/sti_gdp.c | 6 ++-- drivers/gpu/drm/sti/sti_hqvdp.c | 6 ++-- drivers/gpu/drm/sun4i/sun4i_backend.c | 12 ++++---- drivers/gpu/drm/sun4i/sun4i_frontend.c | 22 +++++++------- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 14 ++++----- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 14 ++++----- drivers/gpu/drm/tidss/tidss_dispc.c | 16 +++++----- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 +- drivers/gpu/drm/tiny/arcpgu.c | 2 +- drivers/gpu/drm/vc4/vc4_bo.c | 2 +- drivers/gpu/drm/vc4/vc4_gem.c | 8 ++--- drivers/gpu/drm/vc4/vc4_irq.c | 2 +- drivers/gpu/drm/vc4/vc4_plane.c | 4 +-- drivers/gpu/drm/vc4/vc4_render_cl.c | 14 ++++----- drivers/gpu/drm/vc4/vc4_txp.c | 2 +- drivers/gpu/drm/vc4/vc4_v3d.c | 4 +-- drivers/gpu/drm/vc4/vc4_validate.c | 12 ++++---- drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ++-- include/drm/drm_gem_dma_helper.h | 4 +-- 39 files changed, 142 insertions(+), 137 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index f1b27db5dad5..df5da5a44755 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -137,7 +137,7 @@ komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb, } min_size = komeda_fb_get_pixel_addr(kfb, 0, fb->height, i) - - to_drm_gem_dma_obj(obj)->paddr; + - to_drm_gem_dma_obj(obj)->dma_addr; if (obj->size < min_size) { DRM_DEBUG_KMS("The fb->obj[%d] size: 0x%zx lower than the minimum requirement: 0x%llx.\n", i, obj->size, min_size); @@ -260,7 +260,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane) + plane_y * fb->pitches[plane]; } - return obj->paddr + offset; + return obj->dma_addr + offset; } /* if the fb can be supported by a specific layer */ diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index cefae03f1bcc..ef76d0e6ee2f 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -170,7 +170,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, return -EINVAL; } mw_state->pitches[i] = fb->pitches[i]; - mw_state->addrs[i] = obj->paddr + fb->offsets[i]; + mw_state->addrs[i] = obj->dma_addr + fb->offsets[i]; } mw_state->n_planes = n_planes; diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index b7948ca0060c..45f5e35e7f24 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -714,7 +714,7 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, struct malidp_plane *mp, int plane_index) { - dma_addr_t paddr; + dma_addr_t dma_addr; u16 ptr; struct drm_plane *plane = &mp->base; bool afbc = fb->modifier ? true : false; @@ -729,8 +729,8 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, * and _AD_CROP_V registers. */ if (!afbc) { - paddr = drm_fb_dma_get_gem_addr(fb, plane->state, - plane_index); + dma_addr = drm_fb_dma_get_gem_addr(fb, plane->state, + plane_index); } else { struct drm_gem_dma_object *obj; @@ -738,11 +738,11 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, if (WARN_ON(!obj)) return; - paddr = obj->paddr; + dma_addr = obj->dma_addr; } - malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr); - malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4); + malidp_hw_write(mp->hwdev, lower_32_bits(dma_addr), ptr); + malidp_hw_write(mp->hwdev, upper_32_bits(dma_addr), ptr + 4); } static void malidp_de_set_plane_afbc(struct drm_plane *plane) diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index 996b03bac87f..55a3444a51d8 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -188,7 +188,7 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, gem = drm_fb_dma_get_gem_obj(fb, 0); if (!gem) return; - writel(gem->paddr, priv->base + CRT_ADDR); + writel(gem->dma_addr, priv->base + CRT_ADDR); } static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 48481aa2731a..daa508504f47 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -450,7 +450,7 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, for (i = 0; i < state->nplanes; i++) { struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); - state->dscrs[i]->addr = gem->paddr + state->offsets[i]; + state->dscrs[i]->addr = gem->dma_addr + state->offsets[i]; atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_PLANE_HEAD(i), diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c index b601073c22de..3b535ad1b07c 100644 --- a/drivers/gpu/drm/drm_fb_dma_helper.c +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -72,7 +72,7 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, unsigned int plane) { struct drm_gem_dma_object *obj; - dma_addr_t paddr; + dma_addr_t dma_addr; u8 h_div = 1, v_div = 1; u32 block_w = drm_format_info_block_width(fb->format, plane); u32 block_h = drm_format_info_block_height(fb->format, plane); @@ -86,7 +86,7 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, if (!obj) return 0; - paddr = obj->paddr + fb->offsets[plane]; + dma_addr = obj->dma_addr + fb->offsets[plane]; if (plane > 0) { h_div = fb->format->hsub; @@ -98,10 +98,10 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, block_start_y = (sample_y / block_h) * block_h; num_hblocks = sample_x / block_w; - paddr += fb->pitches[plane] * block_start_y; - paddr += block_size * num_hblocks; + dma_addr += fb->pitches[plane] * block_start_y; + dma_addr += block_size * num_hblocks; - return paddr; + return dma_addr; } EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr); diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c index f1780c01c928..f6901ff97bbb 100644 --- a/drivers/gpu/drm/drm_gem_dma_helper.c +++ b/drivers/gpu/drm/drm_gem_dma_helper.c @@ -145,11 +145,12 @@ struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm, if (dma_obj->map_noncoherent) { dma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size, - &dma_obj->paddr, + &dma_obj->dma_addr, DMA_TO_DEVICE, GFP_KERNEL | __GFP_NOWARN); } else { - dma_obj->vaddr = dma_alloc_wc(drm->dev, size, &dma_obj->paddr, + dma_obj->vaddr = dma_alloc_wc(drm->dev, size, + &dma_obj->dma_addr, GFP_KERNEL | __GFP_NOWARN); } if (!dma_obj->vaddr) { @@ -234,11 +235,11 @@ void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj) } else if (dma_obj->vaddr) { if (dma_obj->map_noncoherent) dma_free_noncoherent(gem_obj->dev->dev, dma_obj->base.size, - dma_obj->vaddr, dma_obj->paddr, + dma_obj->vaddr, dma_obj->dma_addr, DMA_TO_DEVICE); else dma_free_wc(gem_obj->dev->dev, dma_obj->base.size, - dma_obj->vaddr, dma_obj->paddr); + dma_obj->vaddr, dma_obj->dma_addr); } drm_gem_object_release(gem_obj); @@ -396,12 +397,12 @@ EXPORT_SYMBOL_GPL(drm_gem_dma_get_unmapped_area); * @p: DRM printer * @indent: Tab indentation level * - * This function prints paddr and vaddr for use in e.g. debugfs output. + * This function prints dma_addr and vaddr for use in e.g. debugfs output. */ void drm_gem_dma_print_info(const struct drm_gem_dma_object *dma_obj, struct drm_printer *p, unsigned int indent) { - drm_printf_indent(p, indent, "paddr=%pad\n", &dma_obj->paddr); + drm_printf_indent(p, indent, "dma_addr=%pad\n", &dma_obj->dma_addr); drm_printf_indent(p, indent, "vaddr=%p\n", dma_obj->vaddr); } EXPORT_SYMBOL(drm_gem_dma_print_info); @@ -428,7 +429,7 @@ struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj) return ERR_PTR(-ENOMEM); ret = dma_get_sgtable(obj->dev->dev, sgt, dma_obj->vaddr, - dma_obj->paddr, obj->size); + dma_obj->dma_addr, obj->size); if (ret < 0) goto out; @@ -473,10 +474,11 @@ drm_gem_dma_prime_import_sg_table(struct drm_device *dev, if (IS_ERR(dma_obj)) return ERR_CAST(dma_obj); - dma_obj->paddr = sg_dma_address(sgt->sgl); + dma_obj->dma_addr = sg_dma_address(sgt->sgl); dma_obj->sgt = sgt; - DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->paddr, attach->dmabuf->size); + DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->dma_addr, + attach->dmabuf->size); return &dma_obj->base; } @@ -539,7 +541,8 @@ int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct * virt_to_page(dma_obj->vaddr)); } else { ret = dma_mmap_wc(dma_obj->base.dev->dev, vma, dma_obj->vaddr, - dma_obj->paddr, vma->vm_end - vma->vm_start); + dma_obj->dma_addr, + vma->vm_end - vma->vm_start); } if (ret) drm_gem_vm_close(vma); diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index 48c98331a3c0..794a87d16f88 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -136,7 +136,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, DCU_LAYER_POSY(new_state->crtc_y) | DCU_LAYER_POSX(new_state->crtc_x)); regmap_write(fsl_dev->regmap, - DCU_CTRLDESCLN(index, 3), gem->paddr); + DCU_CTRLDESCLN(index, 3), gem->dma_addr); regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), DCU_LAYER_EN | DCU_LAYER_TRANS(0xff) | diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 9666d71a83cc..871f79a6b17e 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -551,10 +551,10 @@ static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, 0); u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; u32 stride = fb->pitches[0]; - u32 addr = (u32)obj->paddr + y * stride; + u32 addr = (u32) obj->dma_addr + y * stride; DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n", - ch + 1, y, in_h, stride, (u32)obj->paddr); + ch + 1, y, in_h, stride, (u32) obj->dma_addr); DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%p4cc)\n", addr, fb->width, fb->height, fmt, &fb->format->format); diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c index 4c41c93ac900..ab6d32bad756 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-plane.c +++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c @@ -224,20 +224,20 @@ static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) if (!format->is_yuv || format->format == DRM_FORMAT_NV12 || format->format == DRM_FORMAT_NV21) - p1_ba = dma_obj->paddr + fb->offsets[0] + + p1_ba = dma_obj->dma_addr + fb->offsets[0] + fb->pitches[0] * (state->src.y1 >> 16) + format->char_per_block[0] * (state->src.x1 >> 16); else if (format->format == DRM_FORMAT_UYVY || format->format == DRM_FORMAT_VYUY || format->format == DRM_FORMAT_YUYV || format->format == DRM_FORMAT_YVYU) - p1_ba = dma_obj->paddr + fb->offsets[0] + + p1_ba = dma_obj->dma_addr + fb->offsets[0] + fb->pitches[0] * (state->src.y1 >> 16) + 2 * format->char_per_block[0] * (state->src.x1 >> 17); if (format->format == DRM_FORMAT_NV12 || format->format == DRM_FORMAT_NV21) - p2_ba = dma_obj->paddr + fb->offsets[1] + + p2_ba = dma_obj->dma_addr + fb->offsets[1] + (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) + (state->src.x1 >> 17)) << 1); diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 07c0b9def383..dba4f7d81d69 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -132,7 +132,7 @@ drm_plane_state_to_eba(struct drm_plane_state *state, int plane) dma_obj = drm_fb_dma_get_gem_obj(fb, plane); BUG_ON(!dma_obj); - return dma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y + + return dma_obj->dma_addr + fb->offsets[plane] + fb->pitches[plane] * y + fb->format->cpp[plane] * x; } @@ -151,7 +151,7 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) x /= fb->format->hsub; y /= fb->format->vsub; - return dma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + + return dma_obj->dma_addr + fb->offsets[1] + fb->pitches[1] * y + fb->format->cpp[1] * x - eba; } @@ -170,7 +170,7 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) x /= fb->format->hsub; y /= fb->format->vsub; - return dma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + + return dma_obj->dma_addr + fb->offsets[2] + fb->pitches[2] * y + fb->format->cpp[2] * x - eba; } diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index 9d3ab4a80b1c..7f98de38842b 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -651,7 +651,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, switch (priv->viu.vd1_planes) { case 3: gem = drm_fb_dma_get_gem_obj(fb, 2); - priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2]; + priv->viu.vd1_addr2 = gem->dma_addr + fb->offsets[2]; priv->viu.vd1_stride2 = fb->pitches[2]; priv->viu.vd1_height2 = drm_format_info_plane_height(fb->format, @@ -663,7 +663,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, fallthrough; case 2: gem = drm_fb_dma_get_gem_obj(fb, 1); - priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1]; + priv->viu.vd1_addr1 = gem->dma_addr + fb->offsets[1]; priv->viu.vd1_stride1 = fb->pitches[1]; priv->viu.vd1_height1 = drm_format_info_plane_height(fb->format, @@ -675,7 +675,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, fallthrough; case 1: gem = drm_fb_dma_get_gem_obj(fb, 0); - priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0]; + priv->viu.vd1_addr0 = gem->dma_addr + fb->offsets[0]; priv->viu.vd1_stride0 = fb->pitches[0]; priv->viu.vd1_height0 = drm_format_info_plane_height(fb->format, diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index f7b9f63a1e70..dfd6a9f33dda 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -367,7 +367,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane, /* Update Canvas with buffer address */ gem = drm_fb_dma_get_gem_obj(fb, 0); - priv->viu.osd1_addr = gem->paddr; + priv->viu.osd1_addr = gem->dma_addr; priv->viu.osd1_stride = fb->pitches[0]; priv->viu.osd1_height = fb->height; priv->viu.osd1_width = fb->width; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 0bff493bf2a8..3bcc9c0f2019 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -352,7 +352,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_bridge_state *bridge_state = NULL; struct drm_device *drm = mxsfb->drm; u32 bus_format = 0; - dma_addr_t paddr; + dma_addr_t dma_addr; pm_runtime_get_sync(drm->dev); mxsfb_enable_axi_clk(mxsfb); @@ -388,10 +388,10 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, mxsfb_crtc_mode_set_nofb(mxsfb, bridge_state, bus_format); /* Write cur_buf as well to avoid an initial corrupt frame */ - paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); - if (paddr) { - writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf); - writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); + dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); + if (dma_addr) { + writel(dma_addr, mxsfb->base + mxsfb->devdata->cur_buf); + writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf); } mxsfb_enable_controller(mxsfb); @@ -541,11 +541,11 @@ static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane, struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state, plane); - dma_addr_t paddr; + dma_addr_t dma_addr; - paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); - if (paddr) - writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); + dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); + if (dma_addr) + writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf); } static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane, @@ -556,11 +556,11 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane, struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state, plane); - dma_addr_t paddr; + dma_addr_t dma_addr; u32 ctrl; - paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); - if (!paddr) { + dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); + if (!dma_addr) { writel(0, mxsfb->base + LCDC_AS_CTRL); return; } @@ -571,16 +571,16 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane, * is understood, live with the 16 initial invalid pixels on the first * line and start 64 bytes within the framebuffer. */ - paddr += 64; + dma_addr += 64; - writel(paddr, mxsfb->base + LCDC_AS_NEXT_BUF); + writel(dma_addr, mxsfb->base + LCDC_AS_NEXT_BUF); /* * If the plane was previously disabled, write LCDC_AS_BUF as well to * provide the first buffer. */ if (!old_pstate->fb) - writel(paddr, mxsfb->base + LCDC_AS_BUF); + writel(dma_addr, mxsfb->base + LCDC_AS_BUF); ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index c9b8c4e03c25..21881fb5e84a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -365,7 +365,7 @@ struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev, return ERR_PTR(ret); } - dma_obj->paddr = 0; + dma_obj->dma_addr = 0; dma_obj->sgt = sgt; return gem_obj; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 31024f50cd23..9e1f0cbbf642 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -351,7 +351,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp, for (i = 0; i < state->format->planes; ++i) { gem = drm_fb_dma_get_gem_obj(fb, i); - dma[i] = gem->paddr + fb->offsets[i]; + dma[i] = gem->dma_addr + fb->offsets[i]; } } else { pitch = drm_rect_width(&state->state.src) >> 16; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 0f6c0a08e74d..10b7f1d0877a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -212,7 +212,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, } } else { ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, - gem->paddr, gem->base.size); + gem->dma_addr, gem->base.size); if (ret) goto fail; } diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index bdf3e8841a40..4624c0aff51f 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -293,13 +293,13 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc, bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp; gem = drm_fb_dma_get_gem_obj(fb, 0); - scrtc->dma[0] = gem->paddr + fb->offsets[0] + scrtc->dma[0] = gem->dma_addr + fb->offsets[0] + y * fb->pitches[0] + x * bpp / 8; if (scrtc->format->yuv) { bpp = scrtc->format->bpp - 8; gem = drm_fb_dma_get_gem_obj(fb, 1); - scrtc->dma[1] = gem->paddr + fb->offsets[1] + scrtc->dma[1] = gem->dma_addr + fb->offsets[1] + y / (bpp == 4 ? 2 : 1) * fb->pitches[1] + x * (bpp == 16 ? 2 : 1); } diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 6d167e858d86..54228424793a 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -46,13 +46,13 @@ static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane, bpp = splane->format->yuv ? 8 : splane->format->bpp; gem = drm_fb_dma_get_gem_obj(fb, 0); - splane->dma[0] = gem->paddr + fb->offsets[0] + splane->dma[0] = gem->dma_addr + fb->offsets[0] + y * fb->pitches[0] + x * bpp / 8; if (splane->format->yuv) { bpp = splane->format->bpp - 8; gem = drm_fb_dma_get_gem_obj(fb, 1); - splane->dma[1] = gem->paddr + fb->offsets[1] + splane->dma[1] = gem->dma_addr + fb->offsets[1] + y / (bpp == 4 ? 2 : 1) * fb->pitches[1] + x * (bpp == 16 ? 2 : 1); } diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c index 44c0fba93607..88f4259680f1 100644 --- a/drivers/gpu/drm/sprd/sprd_dpu.c +++ b/drivers/gpu/drm/sprd/sprd_dpu.c @@ -341,7 +341,7 @@ static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state) for (i = 0; i < fb->format->num_planes; i++) { dma_obj = drm_fb_dma_get_gem_obj(fb, i); - addr = dma_obj->paddr + fb->offsets[i]; + addr = dma_obj->dma_addr + fb->offsets[i]; if (i == 0) layer_reg_wr(ctx, REG_LAY_BASE_ADDR0, addr, index); diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 3ce9d4992176..43c72c2604a0 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -782,11 +782,11 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, - (unsigned long)dma_obj->paddr); + (unsigned long) dma_obj->dma_addr); /* pixel memory location */ bpp = fb->format->cpp[0]; - top_field->gam_gdp_pml = (u32)dma_obj->paddr + fb->offsets[0]; + top_field->gam_gdp_pml = (u32) dma_obj->dma_addr + fb->offsets[0]; top_field->gam_gdp_pml += src_x * bpp; top_field->gam_gdp_pml += src_y * fb->pitches[0]; @@ -831,7 +831,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, dev_dbg(gdp->dev, "Current NVN:0x%X\n", readl(gdp->regs + GAM_GDP_NVN_OFFSET)); dev_dbg(gdp->dev, "Posted buff: %lx current buff: %x\n", - (unsigned long)dma_obj->paddr, + (unsigned long) dma_obj->dma_addr, readl(gdp->regs + GAM_GDP_PML_OFFSET)); if (!curr_list) { diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index ee274140274d..02b77279f6e4 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1182,11 +1182,11 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, - (unsigned long)dma_obj->paddr); + (unsigned long) dma_obj->dma_addr); /* Buffer planes address */ - cmd->top.current_luma = (u32)dma_obj->paddr + fb->offsets[0]; - cmd->top.current_chroma = (u32)dma_obj->paddr + fb->offsets[1]; + cmd->top.current_luma = (u32) dma_obj->dma_addr + fb->offsets[0]; + cmd->top.current_chroma = (u32) dma_obj->dma_addr + fb->offsets[1]; /* Pitches */ cmd->top.luma_processed_pitch = fb->pitches[0]; diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 1fbdd4961194..38070fc261f3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -329,7 +329,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, struct drm_plane_state *state = plane->state; struct drm_framebuffer *fb = state->fb; u32 lo_paddr, hi_paddr; - dma_addr_t paddr; + dma_addr_t dma_addr; /* Set the line width */ DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8); @@ -338,21 +338,21 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, fb->pitches[0] * 8); /* Get the start of the displayed memory */ - paddr = drm_fb_dma_get_gem_addr(fb, state, 0); - DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); + dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0); + DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &dma_addr); if (fb->format->is_yuv) - return sun4i_backend_update_yuv_buffer(backend, fb, paddr); + return sun4i_backend_update_yuv_buffer(backend, fb, dma_addr); /* Write the 32 lower bits of the address (in bits) */ - lo_paddr = paddr << 3; + lo_paddr = dma_addr << 3; DRM_DEBUG_DRIVER("Setting address lower bits to 0x%x\n", lo_paddr); regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYFB_L32ADD_REG(layer), lo_paddr); /* And the upper bits */ - hi_paddr = paddr >> 29; + hi_paddr = dma_addr >> 29; DRM_DEBUG_DRIVER("Setting address high bits to 0x%x\n", hi_paddr); regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_LAYFB_H4ADD_REG, SUN4I_BACKEND_LAYFB_H4ADD_MSK(layer), diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index baeeda04691f..799ab7460ae5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -160,7 +160,7 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, struct drm_framebuffer *fb = state->fb; unsigned int strides[3] = {}; - dma_addr_t paddr; + dma_addr_t dma_addr; bool swap; if (fb->modifier == DRM_FORMAT_MOD_ALLWINNER_TILED) { @@ -221,22 +221,24 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format); /* Set the physical address of the buffer in memory */ - paddr = drm_fb_dma_get_gem_addr(fb, state, 0); - DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr); - regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); + dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0); + DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &dma_addr); + regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, dma_addr); if (fb->format->num_planes > 1) { - paddr = drm_fb_dma_get_gem_addr(fb, state, swap ? 2 : 1); - DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); + dma_addr = drm_fb_dma_get_gem_addr(fb, state, swap ? 2 : 1); + DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", + &dma_addr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, - paddr); + dma_addr); } if (fb->format->num_planes > 2) { - paddr = drm_fb_dma_get_gem_addr(fb, state, swap ? 1 : 2); - DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr); + dma_addr = drm_fb_dma_get_gem_addr(fb, state, swap ? 1 : 2); + DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", + &dma_addr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG, - paddr); + dma_addr); } } EXPORT_SYMBOL(sun4i_frontend_update_buffer); diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 090523356193..ca75ca0835a6 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -193,7 +193,7 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel, struct drm_plane_state *state = plane->state; struct drm_framebuffer *fb = state->fb; struct drm_gem_dma_object *gem; - dma_addr_t paddr; + dma_addr_t dma_addr; u32 ch_base; int bpp; @@ -202,15 +202,15 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel, /* Get the physical address of the buffer in memory */ gem = drm_fb_dma_get_gem_obj(fb, 0); - DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); + DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr); /* Compute the start of the displayed memory */ bpp = fb->format->cpp[0]; - paddr = gem->paddr + fb->offsets[0]; + dma_addr = gem->dma_addr + fb->offsets[0]; /* Fixup framebuffer address for src coordinates */ - paddr += (state->src.x1 >> 16) * bpp; - paddr += (state->src.y1 >> 16) * fb->pitches[0]; + dma_addr += (state->src.x1 >> 16) * bpp; + dma_addr += (state->src.y1 >> 16) * fb->pitches[0]; /* Set the line width */ DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]); @@ -218,11 +218,11 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch_base, overlay), fb->pitches[0]); - DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); + DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &dma_addr); regmap_write(mixer->engine.regs, SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch_base, overlay), - lower_32_bits(paddr)); + lower_32_bits(dma_addr)); return 0; } diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 8def7e0290ce..f9c0a56d3a14 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -310,7 +310,7 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, const struct drm_format_info *format = fb->format; struct drm_gem_dma_object *gem; u32 dx, dy, src_x, src_y; - dma_addr_t paddr; + dma_addr_t dma_addr; u32 ch_base; int i; @@ -324,10 +324,10 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, /* Get the physical address of the buffer in memory */ gem = drm_fb_dma_get_gem_obj(fb, i); - DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); + DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr); /* Compute the start of the displayed memory */ - paddr = gem->paddr + fb->offsets[i]; + dma_addr = gem->dma_addr + fb->offsets[i]; dx = src_x; dy = src_y; @@ -338,8 +338,8 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, } /* Fixup framebuffer address for src coordinates */ - paddr += dx * format->cpp[i]; - paddr += dy * fb->pitches[i]; + dma_addr += dx * format->cpp[i]; + dma_addr += dy * fb->pitches[i]; /* Set the line width */ DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n", @@ -350,12 +350,12 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, fb->pitches[i]); DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n", - i + 1, &paddr); + i + 1, &dma_addr); regmap_write(mixer->engine.regs, SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base, overlay, i), - lower_32_bits(paddr)); + lower_32_bits(dma_addr)); } return 0; diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index 6f3fa37b9ca0..ad93acc9abd2 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -1954,7 +1954,7 @@ int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane, } static -dma_addr_t dispc_plane_state_paddr(const struct drm_plane_state *state) +dma_addr_t dispc_plane_state_dma_addr(const struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; struct drm_gem_dma_object *gem; @@ -1963,7 +1963,7 @@ dma_addr_t dispc_plane_state_paddr(const struct drm_plane_state *state) gem = drm_fb_dma_get_gem_obj(state->fb, 0); - return gem->paddr + fb->offsets[0] + x * fb->format->cpp[0] + + return gem->dma_addr + fb->offsets[0] + x * fb->format->cpp[0] + y * fb->pitches[0]; } @@ -1980,7 +1980,7 @@ dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state) gem = drm_fb_dma_get_gem_obj(fb, 1); - return gem->paddr + fb->offsets[1] + + return gem->dma_addr + fb->offsets[1] + (x * fb->format->cpp[1] / fb->format->hsub) + (y * fb->pitches[1] / fb->format->vsub); } @@ -1993,17 +1993,17 @@ int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, u32 fourcc = state->fb->format->format; u16 cpp = state->fb->format->cpp[0]; u32 fb_width = state->fb->pitches[0] / cpp; - dma_addr_t paddr = dispc_plane_state_paddr(state); + dma_addr_t dma_addr = dispc_plane_state_dma_addr(state); struct dispc_scaling_params scale; dispc_vid_calc_scaling(dispc, state, &scale, lite); dispc_plane_set_pixel_format(dispc, hw_plane, fourcc); - dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_0, paddr & 0xffffffff); - dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_0, (u64)paddr >> 32); - dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_1, paddr & 0xffffffff); - dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_1, (u64)paddr >> 32); + dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_0, dma_addr & 0xffffffff); + dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_0, (u64)dma_addr >> 32); + dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_1, dma_addr & 0xffffffff); + dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_1, (u64)dma_addr >> 32); dispc_vid_write(dispc, hw_plane, DISPC_VID_PICTURE_SIZE, (scale.in_w - 1) | ((scale.in_h - 1) << 16)); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 9034b9778539..b5f60b2b2d0e 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -70,7 +70,7 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) gem = drm_fb_dma_get_gem_obj(fb, 0); - start = gem->paddr + fb->offsets[0] + + start = gem->dma_addr + fb->offsets[0] + crtc->y * fb->pitches[0] + crtc->x * fb->format->cpp[0]; diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c index 21d9e0bd67ba..bb302a3fd6b5 100644 --- a/drivers/gpu/drm/tiny/arcpgu.c +++ b/drivers/gpu/drm/tiny/arcpgu.c @@ -227,7 +227,7 @@ static void arc_pgu_update(struct drm_simple_display_pipe *pipe, arcpgu = pipe_to_arcpgu_priv(pipe); gem = drm_fb_dma_get_gem_obj(pipe->plane.state->fb, 0); - arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr); + arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->dma_addr); } static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = { diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 07f57910c9e8..231add8b8e12 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -303,7 +303,7 @@ static void vc4_bo_purge(struct drm_gem_object *obj) drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping); - dma_free_wc(dev->dev, obj->size, bo->base.vaddr, bo->base.paddr); + dma_free_wc(dev->dev, obj->size, bo->base.vaddr, bo->base.dma_addr); bo->base.vaddr = NULL; bo->madv = __VC4_MADV_PURGED; } diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 56a0af281b92..628d40ff3aa1 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -126,7 +126,7 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, goto err_delete_handle; } bo_state[i].handle = handle; - bo_state[i].paddr = vc4_bo->base.paddr; + bo_state[i].paddr = vc4_bo->base.dma_addr; bo_state[i].size = vc4_bo->base.base.size; } @@ -917,16 +917,16 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) list_add_tail(&to_vc4_bo(&exec->exec_bo->base)->unref_head, &exec->unref_list); - exec->ct0ca = exec->exec_bo->paddr + bin_offset; + exec->ct0ca = exec->exec_bo->dma_addr + bin_offset; exec->bin_u = bin; exec->shader_rec_v = exec->exec_bo->vaddr + shader_rec_offset; - exec->shader_rec_p = exec->exec_bo->paddr + shader_rec_offset; + exec->shader_rec_p = exec->exec_bo->dma_addr + shader_rec_offset; exec->shader_rec_size = args->shader_rec_size; exec->uniforms_v = exec->exec_bo->vaddr + uniforms_offset; - exec->uniforms_p = exec->exec_bo->paddr + uniforms_offset; + exec->uniforms_p = exec->exec_bo->dma_addr + uniforms_offset; exec->uniforms_size = args->uniforms_size; ret = vc4_validate_bin_cl(dev, diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index a9fc63d9a7f0..1e6db0121ccd 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -105,7 +105,7 @@ vc4_overflow_mem_work(struct work_struct *work) } vc4->bin_alloc_overflow = BIT(bin_bo_slot); - V3D_WRITE(V3D_BPOA, bo->base.paddr + bin_bo_slot * vc4->bin_alloc_size); + V3D_WRITE(V3D_BPOA, bo->base.dma_addr + bin_bo_slot * vc4->bin_alloc_size); V3D_WRITE(V3D_BPOS, bo->base.base.size); V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM); V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index b76b0e602c81..eff9c63adfa7 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -359,7 +359,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) return ret; for (i = 0; i < num_planes; i++) - vc4_state->offsets[i] = bo->paddr + fb->offsets[i]; + vc4_state->offsets[i] = bo->dma_addr + fb->offsets[i]; /* * We don't support subpixel source positioning for scaling, @@ -1250,7 +1250,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) * because this is only called on the primary plane. */ WARN_ON_ONCE(plane->state->crtc_x < 0 || plane->state->crtc_y < 0); - addr = bo->paddr + fb->offsets[0]; + addr = bo->dma_addr + fb->offsets[0]; /* Write the new address into the hardware immediately. The * scanout will start from this address as soon as the FIFO diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c index c8a92023238c..1bda5010f15a 100644 --- a/drivers/gpu/drm/vc4/vc4_render_cl.c +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c @@ -101,7 +101,7 @@ static uint32_t vc4_full_res_offset(struct vc4_exec_info *exec, struct drm_vc4_submit_rcl_surface *surf, uint8_t x, uint8_t y) { - return bo->paddr + surf->offset + VC4_TILE_BUFFER_SIZE * + return bo->dma_addr + surf->offset + VC4_TILE_BUFFER_SIZE * (DIV_ROUND_UP(exec->args->width, 32) * y + x); } @@ -142,7 +142,7 @@ static void emit_tile(struct vc4_exec_info *exec, } else { rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL); rcl_u16(setup, args->color_read.bits); - rcl_u32(setup, setup->color_read->paddr + + rcl_u32(setup, setup->color_read->dma_addr + args->color_read.offset); } } @@ -164,7 +164,7 @@ static void emit_tile(struct vc4_exec_info *exec, } else { rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL); rcl_u16(setup, args->zs_read.bits); - rcl_u32(setup, setup->zs_read->paddr + + rcl_u32(setup, setup->zs_read->dma_addr + args->zs_read.offset); } } @@ -232,7 +232,7 @@ static void emit_tile(struct vc4_exec_info *exec, (last_tile_write ? 0 : VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR)); rcl_u32(setup, - (setup->zs_write->paddr + args->zs_write.offset) | + (setup->zs_write->dma_addr + args->zs_write.offset) | ((last && last_tile_write) ? VC4_LOADSTORE_TILE_BUFFER_EOF : 0)); } @@ -355,7 +355,7 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); rcl_u32(setup, - (setup->color_write ? (setup->color_write->paddr + + (setup->color_write ? (setup->color_write->dma_addr + args->color_write.offset) : 0)); rcl_u16(setup, args->width); @@ -374,8 +374,8 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, } BUG_ON(setup->next_offset != size); - exec->ct1ca = setup->rcl->paddr; - exec->ct1ea = setup->rcl->paddr + setup->next_offset; + exec->ct1ca = setup->rcl->dma_addr; + exec->ct1ea = setup->rcl->dma_addr + setup->next_offset; return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 811bc7d9b90c..bd181b5a7b52 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -318,7 +318,7 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, return; gem = drm_fb_dma_get_gem_obj(fb, 0); - TXP_WRITE(TXP_DST_PTR, gem->paddr + fb->offsets[0]); + TXP_WRITE(TXP_DST_PTR, gem->dma_addr + fb->offsets[0]); TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); TXP_WRITE(TXP_DIM, VC4_SET_FIELD(mode->hdisplay, TXP_WIDTH) | diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 6222c884dcbb..56abb0d6bc39 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -268,8 +268,8 @@ static int bin_bo_alloc(struct vc4_dev *vc4) } /* Check if this BO won't trigger the addressing bug. */ - if ((bo->base.paddr & 0xf0000000) == - ((bo->base.paddr + bo->base.base.size - 1) & 0xf0000000)) { + if ((bo->base.dma_addr & 0xf0000000) == + ((bo->base.dma_addr + bo->base.base.size - 1) & 0xf0000000)) { vc4->bin_bo = bo; /* Set up for allocating 512KB chunks of diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index d5dc6b51ec69..520231af4df9 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -294,7 +294,7 @@ validate_indexed_prim_list(VALIDATE_ARGS) return -EINVAL; } - *(uint32_t *)(validated + 5) = ib->paddr + offset; + *(uint32_t *)(validated + 5) = ib->dma_addr + offset; return 0; } @@ -400,7 +400,7 @@ validate_tile_binning_config(VALIDATE_ARGS) * free when the job completes rendering. */ exec->bin_slots |= BIT(bin_slot); - bin_addr = vc4->bin_bo->base.paddr + bin_slot * vc4->bin_alloc_size; + bin_addr = vc4->bin_bo->base.dma_addr + bin_slot * vc4->bin_alloc_size; /* The tile state data array is 48 bytes per tile, and we put it at * the start of a BO containing both it and the tile alloc. @@ -608,7 +608,7 @@ reloc_tex(struct vc4_exec_info *exec, "outside of UBO\n"); goto fail; } - *validated_p0 = tex->paddr + p0; + *validated_p0 = tex->dma_addr + p0; return true; } @@ -736,7 +736,7 @@ reloc_tex(struct vc4_exec_info *exec, offset -= level_size; } - *validated_p0 = tex->paddr + p0; + *validated_p0 = tex->dma_addr + p0; if (is_cs) { exec->bin_dep_seqno = max(exec->bin_dep_seqno, @@ -840,7 +840,7 @@ validate_gl_shader_rec(struct drm_device *dev, void *uniform_data_u; uint32_t tex, uni; - *(uint32_t *)(pkt_v + o) = bo[i]->paddr + src_offset; + *(uint32_t *)(pkt_v + o) = bo[i]->dma_addr + src_offset; if (src_offset != 0) { DRM_DEBUG("Shaders must be at offset 0 of " @@ -928,7 +928,7 @@ validate_gl_shader_rec(struct drm_device *dev, } } - *(uint32_t *)(pkt_v + o) = vbo->paddr + offset; + *(uint32_t *)(pkt_v + o) = vbo->dma_addr + offset; } return 0; diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index 3bcb71c71db0..bbb365f2d087 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -1098,14 +1098,14 @@ static int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer, unsigned int height = state->crtc_h / (i ? info->vsub : 1); struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; struct dma_async_tx_descriptor *desc; - dma_addr_t paddr; + dma_addr_t dma_addr; - paddr = drm_fb_dma_get_gem_addr(state->fb, state, i); + dma_addr = drm_fb_dma_get_gem_addr(state->fb, state, i); dma->xt.numf = height; dma->sgl.size = width * info->cpp[i]; dma->sgl.icg = state->fb->pitches[i] - dma->sgl.size; - dma->xt.src_start = paddr; + dma->xt.src_start = dma_addr; dma->xt.frame_size = 1; dma->xt.dir = DMA_MEM_TO_DEV; dma->xt.src_sgl = true; diff --git a/include/drm/drm_gem_dma_helper.h b/include/drm/drm_gem_dma_helper.h index 82805069b37a..8a043235dad8 100644 --- a/include/drm/drm_gem_dma_helper.h +++ b/include/drm/drm_gem_dma_helper.h @@ -11,7 +11,7 @@ struct drm_mode_create_dumb; /** * struct drm_gem_dma_object - GEM object backed by DMA memory allocations * @base: base GEM object - * @paddr: DMA address of the backing memory + * @dma_addr: DMA address of the backing memory * @sgt: scatter/gather table for imported PRIME buffers. The table can have * more than one entry but they are guaranteed to have contiguous * DMA addresses. @@ -20,7 +20,7 @@ struct drm_mode_create_dumb; */ struct drm_gem_dma_object { struct drm_gem_object base; - dma_addr_t paddr; + dma_addr_t dma_addr; struct sg_table *sgt; /* For objects with DMA memory allocated by GEM DMA */ From 1d8104e01c416bd93bc7648fa40a4aaf93371a91 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Tue, 2 Aug 2022 02:04:05 +0200 Subject: [PATCH 241/396] drm/todo: remove task to rename CMA helpers Both, GEM and FB, CMA helpers were renamed to "GEM DMA" and "FB DMA", hence the task can be removed. Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220802000405.949236-6-dakr@redhat.com --- Documentation/gpu/todo.rst | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index de226ccc2c54..7634c27ac562 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -331,19 +331,6 @@ converted, except for struct drm_driver.gem_prime_mmap. Level: Intermediate -Rename CMA helpers to DMA helpers ---------------------------------- - -CMA (standing for contiguous memory allocator) is really a bit an accident of -what these were used for first, a much better name would be DMA helpers. In the -text these should even be called coherent DMA memory helpers (so maybe CDM, but -no one knows what that means) since underneath they just use dma_alloc_coherent. - -Contact: Laurent Pinchart, Daniel Vetter - -Level: Intermediate (mostly because it is a huge tasks without good partial -milestones, not technically itself that challenging) - connector register/unregister fixes ----------------------------------- From 37c7c23a6420f56a66d70e30ed54ae8f77349f90 Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Wed, 3 Aug 2022 20:42:47 +0000 Subject: [PATCH 242/396] drm: fix whitespace in drm_plane_create_color_properties() The drm_property_create_enum() call for "COLOR_RANGE" contains a tab character in the middle of the argument list. Signed-off-by: Simon Ser <contact@emersion.fr> Reviewed-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220803204240.33409-1-contact@emersion.fr --- drivers/gpu/drm/drm_color_mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 17c6c3eefcd6..d021497841b8 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -575,7 +575,7 @@ int drm_plane_create_color_properties(struct drm_plane *plane, len++; } - prop = drm_property_create_enum(dev, 0, "COLOR_RANGE", + prop = drm_property_create_enum(dev, 0, "COLOR_RANGE", enum_list, len); if (!prop) return -ENOMEM; From ffb6260be81f5f4c97b34430072bf50380b42478 Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Tue, 19 Jul 2022 12:47:22 +0300 Subject: [PATCH 243/396] drm/vmwgfx: clean up some error pointer checking The vmw_user_bo_noref_lookup() function cannot return NULL. If it could, then this function would return PTR_ERR(NULL) which is success. Returning success without initializing "*vmw_bo_p = vmw_bo;" would lead to an uninitialized variable bug in the caller. Smatch complains about this: drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c:1177 vmw_translate_mob_ptr() warn: passing zero to 'PTR_ERR' drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c:1314 vmw_cmd_dx_bind_query() error: uninitialized symbol 'vmw_bo'. Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Zack Rusin <zackr@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/YtZ9qrKeBqmmK8Hv@kili --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index d49de4905efa..f085dbd4736d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -1172,7 +1172,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, vmw_validation_preload_bo(sw_context->ctx); vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle); - if (IS_ERR_OR_NULL(vmw_bo)) { + if (IS_ERR(vmw_bo)) { VMW_DEBUG_USER("Could not find or use MOB buffer.\n"); return PTR_ERR(vmw_bo); } @@ -1226,7 +1226,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, vmw_validation_preload_bo(sw_context->ctx); vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle); - if (IS_ERR_OR_NULL(vmw_bo)) { + if (IS_ERR(vmw_bo)) { VMW_DEBUG_USER("Could not find or use GMR region.\n"); return PTR_ERR(vmw_bo); } From 05436815fdb47539269387c10285c088a8ba33e7 Mon Sep 17 00:00:00 2001 From: Tom Rix <trix@redhat.com> Date: Sat, 30 Jul 2022 09:57:04 -0400 Subject: [PATCH 244/396] drm/vmwgfx: cleanup comments Remove second 'should' Spelling replacements aqcuire -> acquire applcations -> applications assumings -> assumes begining -> beginning commited -> committed contol -> control inbetween -> in between resorces -> resources succesful -> successful successfule -> successful Signed-off-by: Tom Rix <trix@redhat.com> Signed-off-by: Zack Rusin <zackr@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220730135704.2889434-1-trix@redhat.com --- drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h | 2 +- drivers/gpu/drm/vmwgfx/ttm_object.h | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c | 8 ++++---- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 8 ++++---- drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h b/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h index 1f6e3bbc6605..f84376718086 100644 --- a/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h +++ b/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h @@ -121,7 +121,7 @@ typedef __attribute__((aligned(32))) struct MKSGuestStatInfoEntry { * * Since the MKSGuestStatInfoEntry structures contain userlevel * pointers, the InstanceDescriptor also contains pointers to the - * begining of these sections allowing the host side code to correctly + * beginning of these sections allowing the host side code to correctly * interpret the pointers. * * Because the host side code never acknowledges anything back to the diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h index 4c8700027c6d..1a2fa0f83f5f 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_object.h +++ b/drivers/gpu/drm/vmwgfx/ttm_object.h @@ -96,7 +96,7 @@ struct ttm_object_device; * * This struct is intended to be used as a base struct for objects that * are visible to user-space. It provides a global name, race-safe - * access and refcounting, minimal access contol and hooks for unref actions. + * access and refcounting, minimal access control and hooks for unref actions. */ struct ttm_base_object { @@ -138,7 +138,7 @@ struct ttm_prime_object { * * @tfile: Pointer to a struct ttm_object_file. * @base: The struct ttm_base_object to initialize. - * @shareable: This object is shareable with other applcations. + * @shareable: This object is shareable with other applications. * (different @tfile pointers.) * @type: The object type. * @refcount_release: See the struct ttm_base_object description. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index eb2fd7694cd1..822251aaab0a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -727,7 +727,7 @@ int vmw_user_bo_lookup(struct drm_file *filp, * Any persistent usage of the object requires a refcount to be taken using * ttm_bo_reference_unless_doomed(). Iff this function returns successfully it * needs to be paired with vmw_user_bo_noref_release() and no sleeping- - * or scheduling functions may be called inbetween these function calls. + * or scheduling functions may be called in between these function calls. * * Return: A struct vmw_buffer_object pointer if successful or negative * error pointer on failure. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c index 415774fde796..82ef58ccdd42 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c @@ -36,7 +36,7 @@ * @res: Refcounted pointer to a struct vmw_resource. * @hash: Hash entry for the manager hash table. * @head: List head used either by the staging list or the manager list - * of commited resources. + * of committed resources. * @state: Staging state of this resource entry. * @man: Pointer to a resource manager for this entry. */ @@ -51,9 +51,9 @@ struct vmw_cmdbuf_res { /** * struct vmw_cmdbuf_res_manager - Command buffer resource manager. * - * @resources: Hash table containing staged and commited command buffer + * @resources: Hash table containing staged and committed command buffer * resources - * @list: List of commited command buffer resources. + * @list: List of committed command buffer resources. * @dev_priv: Pointer to a device private structure. * * @resources and @list are protected by the cmdbuf mutex for now. @@ -118,7 +118,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man, * This function commits a list of command buffer resource * additions or removals. * It is typically called when the execbuf ioctl call triggering these - * actions has commited the fifo contents to the device. + * actions has committed the fifo contents to the device. */ void vmw_cmdbuf_res_commit(struct list_head *list) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 7046dfd0d1c6..85f86faa3243 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -70,7 +70,7 @@ struct vmw_du_update_plane { * * Some surface resource or buffer object need some extra cmd submission * like update GB image for proxy surface and define a GMRFB for screen - * object. That should should be done here as this callback will be + * object. That should be done here as this callback will be * called after FIFO allocation with the address of command buufer. * * This callback is optional. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index a7d62a4eb47b..f66caa540e14 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -525,7 +525,7 @@ void vmw_resource_unreserve(struct vmw_resource *res, * for a resource and in that case, allocate * one, reserve and validate it. * - * @ticket: The ww aqcquire context to use, or NULL if trylocking. + * @ticket: The ww acquire context to use, or NULL if trylocking. * @res: The resource for which to allocate a backup buffer. * @interruptible: Whether any sleeps during allocation should be * performed while interruptible. @@ -686,7 +686,7 @@ out_no_unbind: * @intr: Perform waits interruptible if possible. * @dirtying: Pending GPU operation will dirty the resource * - * On succesful return, any backup DMA buffer pointed to by @res->backup will + * On successful return, any backup DMA buffer pointed to by @res->backup will * be reserved and validated. * On hardware resource shortage, this function will repeatedly evict * resources of the same type until the validation succeeds. @@ -804,7 +804,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) * @dx_query_mob: Buffer containing the DX query MOB * * Read back cached states from the device if they exist. This function - * assumings binding_mutex is held. + * assumes binding_mutex is held. */ int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob) { @@ -1125,7 +1125,7 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start, } /* - * In order of increasing backup_offset, clean dirty resorces + * In order of increasing backup_offset, clean dirty resources * intersecting the range. */ while (found) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c index 483ad544ea54..0d51b4542269 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c @@ -196,7 +196,7 @@ out_ret: * type. * * Returns: Refcounted pointer to the embedded struct vmw_resource if - * successfule. Error pointer otherwise. + * successful. Error pointer otherwise. */ struct vmw_resource * vmw_simple_resource_lookup(struct ttm_object_file *tfile, From 7fbee3eb9ab82c4b8c240617a1b3878c6981dd73 Mon Sep 17 00:00:00 2001 From: Zack Rusin <zackr@vmware.com> Date: Mon, 25 Apr 2022 16:31:51 -0400 Subject: [PATCH 245/396] drm/vmwgfx: Remove unused hugepage support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no point in explicitly trying to align virtual memory to facilitate huge page table entries or huge page memory in buffer objects given that they're not being used. Transparent hugepages support for vram allocations has been gradually retired over the last two years making alignment of unmapped areas unneeded and pointless. Signed-off-by: Zack Rusin <zackr@vmware.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220425203152.1314211-1-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 01a5b47e95f9..d7bd5eb1d3ac 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1398,18 +1398,6 @@ static void vmw_debugfs_resource_managers_init(struct vmw_private *vmw) root, "system_mob_ttm"); } -static unsigned long -vmw_get_unmapped_area(struct file *file, unsigned long uaddr, - unsigned long len, unsigned long pgoff, - unsigned long flags) -{ - struct drm_file *file_priv = file->private_data; - struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); - - return drm_get_unmapped_area(file, uaddr, len, pgoff, flags, - dev_priv->drm.vma_offset_manager); -} - static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, void *ptr) { @@ -1576,7 +1564,6 @@ static const struct file_operations vmwgfx_driver_fops = { .compat_ioctl = vmw_compat_ioctl, #endif .llseek = noop_llseek, - .get_unmapped_area = vmw_get_unmapped_area, }; static const struct drm_driver driver = { From 01224faa36e86a2b9d423fe851c05feb288ae83d Mon Sep 17 00:00:00 2001 From: Zack Rusin <zackr@vmware.com> Date: Mon, 25 Apr 2022 16:31:52 -0400 Subject: [PATCH 246/396] drm: Remove the drm_get_unmapped_area() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This has been only used by the vmwgfx driver and vmwgfx over the last year removed support for transparent hugepages on vram leaving drm_get_unmapped_area completely unused. There's no point in keeping unused code in core drm. Signed-off-by: Zack Rusin <zackr@vmware.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <mripard@kernel.org> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: dri-devel@lists.freedesktop.org Link: https://patchwork.freedesktop.org/patch/msgid/20220425203152.1314211-2-zack@kde.org --- drivers/gpu/drm/drm_file.c | 141 ------------------------------------- include/drm/drm_file.h | 9 --- 2 files changed, 150 deletions(-) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index fa55c9a562f3..63212f02f097 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -48,11 +48,6 @@ #include "drm_internal.h" #include "drm_legacy.h" -#if defined(CONFIG_MMU) && defined(CONFIG_TRANSPARENT_HUGEPAGE) -#include <uapi/asm/mman.h> -#include <drm/drm_vma_manager.h> -#endif - /* from BKL pushdown */ DEFINE_MUTEX(drm_global_mutex); @@ -913,139 +908,3 @@ struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags) return file; } EXPORT_SYMBOL_FOR_TESTS_ONLY(mock_drm_getfile); - -#ifdef CONFIG_MMU -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -/* - * drm_addr_inflate() attempts to construct an aligned area by inflating - * the area size and skipping the unaligned start of the area. - * adapted from shmem_get_unmapped_area() - */ -static unsigned long drm_addr_inflate(unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags, - unsigned long huge_size) -{ - unsigned long offset, inflated_len; - unsigned long inflated_addr; - unsigned long inflated_offset; - - offset = (pgoff << PAGE_SHIFT) & (huge_size - 1); - if (offset && offset + len < 2 * huge_size) - return addr; - if ((addr & (huge_size - 1)) == offset) - return addr; - - inflated_len = len + huge_size - PAGE_SIZE; - if (inflated_len > TASK_SIZE) - return addr; - if (inflated_len < len) - return addr; - - inflated_addr = current->mm->get_unmapped_area(NULL, 0, inflated_len, - 0, flags); - if (IS_ERR_VALUE(inflated_addr)) - return addr; - if (inflated_addr & ~PAGE_MASK) - return addr; - - inflated_offset = inflated_addr & (huge_size - 1); - inflated_addr += offset - inflated_offset; - if (inflated_offset > offset) - inflated_addr += huge_size; - - if (inflated_addr > TASK_SIZE - len) - return addr; - - return inflated_addr; -} - -/** - * drm_get_unmapped_area() - Get an unused user-space virtual memory area - * suitable for huge page table entries. - * @file: The struct file representing the address space being mmap()'d. - * @uaddr: Start address suggested by user-space. - * @len: Length of the area. - * @pgoff: The page offset into the address space. - * @flags: mmap flags - * @mgr: The address space manager used by the drm driver. This argument can - * probably be removed at some point when all drivers use the same - * address space manager. - * - * This function attempts to find an unused user-space virtual memory area - * that can accommodate the size we want to map, and that is properly - * aligned to facilitate huge page table entries matching actual - * huge pages or huge page aligned memory in buffer objects. Buffer objects - * are assumed to start at huge page boundary pfns (io memory) or be - * populated by huge pages aligned to the start of the buffer object - * (system- or coherent memory). Adapted from shmem_get_unmapped_area. - * - * Return: aligned user-space address. - */ -unsigned long drm_get_unmapped_area(struct file *file, - unsigned long uaddr, unsigned long len, - unsigned long pgoff, unsigned long flags, - struct drm_vma_offset_manager *mgr) -{ - unsigned long addr; - unsigned long inflated_addr; - struct drm_vma_offset_node *node; - - if (len > TASK_SIZE) - return -ENOMEM; - - /* - * @pgoff is the file page-offset the huge page boundaries of - * which typically aligns to physical address huge page boundaries. - * That's not true for DRM, however, where physical address huge - * page boundaries instead are aligned with the offset from - * buffer object start. So adjust @pgoff to be the offset from - * buffer object start. - */ - drm_vma_offset_lock_lookup(mgr); - node = drm_vma_offset_lookup_locked(mgr, pgoff, 1); - if (node) - pgoff -= node->vm_node.start; - drm_vma_offset_unlock_lookup(mgr); - - addr = current->mm->get_unmapped_area(file, uaddr, len, pgoff, flags); - if (IS_ERR_VALUE(addr)) - return addr; - if (addr & ~PAGE_MASK) - return addr; - if (addr > TASK_SIZE - len) - return addr; - - if (len < HPAGE_PMD_SIZE) - return addr; - if (flags & MAP_FIXED) - return addr; - /* - * Our priority is to support MAP_SHARED mapped hugely; - * and support MAP_PRIVATE mapped hugely too, until it is COWed. - * But if caller specified an address hint, respect that as before. - */ - if (uaddr) - return addr; - - inflated_addr = drm_addr_inflate(addr, len, pgoff, flags, - HPAGE_PMD_SIZE); - - if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) && - len >= HPAGE_PUD_SIZE) - inflated_addr = drm_addr_inflate(inflated_addr, len, pgoff, - flags, HPAGE_PUD_SIZE); - return inflated_addr; -} -#else /* CONFIG_TRANSPARENT_HUGEPAGE */ -unsigned long drm_get_unmapped_area(struct file *file, - unsigned long uaddr, unsigned long len, - unsigned long pgoff, unsigned long flags, - struct drm_vma_offset_manager *mgr) -{ - return current->mm->get_unmapped_area(file, uaddr, len, pgoff, flags); -} -#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ -EXPORT_SYMBOL_GPL(drm_get_unmapped_area); -#endif /* CONFIG_MMU */ diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index e0a73a1e2df7..d780fd151789 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -421,13 +421,4 @@ void drm_send_event_timestamp_locked(struct drm_device *dev, struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags); -#ifdef CONFIG_MMU -struct drm_vma_offset_manager; -unsigned long drm_get_unmapped_area(struct file *file, - unsigned long uaddr, unsigned long len, - unsigned long pgoff, unsigned long flags, - struct drm_vma_offset_manager *mgr); -#endif /* CONFIG_MMU */ - - #endif /* _DRM_FILE_H_ */ From f9929f69de94212f98b3ad72a3e81c3bd3d333e0 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor <nathan@kernel.org> Date: Mon, 25 Jul 2022 16:36:29 -0700 Subject: [PATCH 247/396] drm/simpledrm: Fix return type of simpledrm_simple_display_pipe_mode_valid() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When booting a kernel compiled with clang's CFI protection (CONFIG_CFI_CLANG), there is a CFI failure in drm_simple_kms_crtc_mode_valid() when trying to call simpledrm_simple_display_pipe_mode_valid() through ->mode_valid(): [ 0.322802] CFI failure (target: simpledrm_simple_display_pipe_mode_valid+0x0/0x8): ... [ 0.324928] Call trace: [ 0.324969] __ubsan_handle_cfi_check_fail+0x58/0x60 [ 0.325053] __cfi_check_fail+0x3c/0x44 [ 0.325120] __cfi_slowpath_diag+0x178/0x200 [ 0.325192] drm_simple_kms_crtc_mode_valid+0x58/0x80 [ 0.325279] __drm_helper_update_and_validate+0x31c/0x464 ... The ->mode_valid() member in 'struct drm_simple_display_pipe_funcs' expects a return type of 'enum drm_mode_status', not 'int'. Correct it to fix the CFI failure. Cc: stable@vger.kernel.org Fixes: 11e8f5fd223b ("drm: Add simpledrm driver") Link: https://github.com/ClangBuiltLinux/linux/issues/1647 Reported-by: Tomasz Paweł Gajc <tpgxyz@gmail.com> Signed-off-by: Nathan Chancellor <nathan@kernel.org> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sami Tolvanen <samitolvanen@google.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220725233629.223223-1-nathan@kernel.org (cherry picked from commit 0c09bc33aa8e9dc867300acaadc318c2f0d85a1e) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/gpu/drm/tiny/simpledrm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 768242a78e2b..5422363690e7 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -627,7 +627,7 @@ static const struct drm_connector_funcs simpledrm_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int +static enum drm_mode_status simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, const struct drm_display_mode *mode) { From 03d38605cee7762d020dc14cfdefa6cef77b5811 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 1 Aug 2022 15:50:24 +0200 Subject: [PATCH 248/396] drm/simpledrm: Remove mem field from device structure Remove the unused mem field from struct simpledrm_device. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220801135028.30647-2-tzimmermann@suse.de --- drivers/gpu/drm/tiny/simpledrm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 5422363690e7..c5a0dabfb6df 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -217,7 +217,6 @@ struct simpledrm_device { unsigned int pitch; /* memory management */ - struct resource *mem; void __iomem *screen_base; /* modesetting */ @@ -558,7 +557,6 @@ static int simpledrm_device_init_mm(struct simpledrm_device *sdev) if (!screen_base) return -ENOMEM; - sdev->mem = mem; sdev->screen_base = screen_base; return 0; From c25b69604fc4455228329c6c522a87974246e40f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 1 Aug 2022 15:50:25 +0200 Subject: [PATCH 249/396] drm/simpledrm: Inline device-init helpers Inline the helpers for initializing the hardware FB, the memory management and the modesetting into the device-creation function. No functional changes. In the original code, init helpers depended on values from other init helpers. Inlining the functions ensures that steps are taken in the correct order. It's also easier to see what happens. The device is simple enough to be set up in one function. Only clocks and regulators are still set up in their own helpers, as their presence is system dependent. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220801135028.30647-3-tzimmermann@suse.de --- drivers/gpu/drm/tiny/simpledrm.c | 307 ++++++++++++++----------------- 1 file changed, 136 insertions(+), 171 deletions(-) diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index c5a0dabfb6df..f458e8bec63e 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -449,119 +449,6 @@ static int simpledrm_device_init_regulators(struct simpledrm_device *sdev) } #endif -/* - * Simplefb settings - */ - -static struct drm_display_mode simpledrm_mode(unsigned int width, - unsigned int height) -{ - struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) }; - - mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */; - drm_mode_set_name(&mode); - - return mode; -} - -static int simpledrm_device_init_fb(struct simpledrm_device *sdev) -{ - int width, height, stride; - const struct drm_format_info *format; - struct drm_device *dev = &sdev->dev; - struct platform_device *pdev = sdev->pdev; - const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev); - struct device_node *of_node = pdev->dev.of_node; - - if (pd) { - width = simplefb_get_width_pd(dev, pd); - if (width < 0) - return width; - height = simplefb_get_height_pd(dev, pd); - if (height < 0) - return height; - stride = simplefb_get_stride_pd(dev, pd); - if (stride < 0) - return stride; - format = simplefb_get_format_pd(dev, pd); - if (IS_ERR(format)) - return PTR_ERR(format); - } else if (of_node) { - width = simplefb_get_width_of(dev, of_node); - if (width < 0) - return width; - height = simplefb_get_height_of(dev, of_node); - if (height < 0) - return height; - stride = simplefb_get_stride_of(dev, of_node); - if (stride < 0) - return stride; - format = simplefb_get_format_of(dev, of_node); - if (IS_ERR(format)) - return PTR_ERR(format); - } else { - drm_err(dev, "no simplefb configuration found\n"); - return -ENODEV; - } - - sdev->mode = simpledrm_mode(width, height); - sdev->format = format; - sdev->pitch = stride; - - drm_dbg_kms(dev, "display mode={" DRM_MODE_FMT "}\n", - DRM_MODE_ARG(&sdev->mode)); - drm_dbg_kms(dev, - "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n", - &format->format, width, height, stride); - - return 0; -} - -/* - * Memory management - */ - -static int simpledrm_device_init_mm(struct simpledrm_device *sdev) -{ - struct drm_device *dev = &sdev->dev; - struct platform_device *pdev = sdev->pdev; - struct resource *res, *mem; - void __iomem *screen_base; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; - - ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res)); - if (ret) { - drm_err(dev, "could not acquire memory range %pr: error %d\n", - res, ret); - return ret; - } - - mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res), - sdev->dev.driver->name); - if (!mem) { - /* - * We cannot make this fatal. Sometimes this comes from magic - * spaces our resource handlers simply don't know about. Use - * the I/O-memory resource as-is and try to map that instead. - */ - drm_warn(dev, "could not acquire memory region %pr\n", res); - mem = res; - } - - screen_base = devm_ioremap_wc(&pdev->dev, mem->start, - resource_size(mem)); - if (!screen_base) - return -ENOMEM; - - sdev->screen_base = screen_base; - - return 0; -} - /* * Modesetting */ @@ -738,6 +625,21 @@ static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; +/* + * Init / Cleanup + */ + +static struct drm_display_mode simpledrm_mode(unsigned int width, + unsigned int height) +{ + struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) }; + + mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */; + drm_mode_set_name(&mode); + + return mode; +} + static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev, size_t *nformats_out) { @@ -777,88 +679,151 @@ out: return sdev->formats; } -static int simpledrm_device_init_modeset(struct simpledrm_device *sdev) +static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, + struct platform_device *pdev) { - struct drm_device *dev = &sdev->dev; - struct drm_display_mode *mode = &sdev->mode; - struct drm_connector *connector = &sdev->connector; - struct drm_simple_display_pipe *pipe = &sdev->pipe; + const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev); + struct device_node *of_node = pdev->dev.of_node; + struct simpledrm_device *sdev; + struct drm_device *dev; + int width, height, stride; + const struct drm_format_info *format; + struct resource *res, *mem; + void __iomem *screen_base; + struct drm_connector *connector; + struct drm_simple_display_pipe *pipe; unsigned long max_width, max_height; const uint32_t *formats; size_t nformats; int ret; - ret = drmm_mode_config_init(dev); - if (ret) - return ret; - - max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH); - max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT); - - dev->mode_config.min_width = mode->hdisplay; - dev->mode_config.max_width = max_width; - dev->mode_config.min_height = mode->vdisplay; - dev->mode_config.max_height = max_height; - dev->mode_config.preferred_depth = sdev->format->cpp[0] * 8; - dev->mode_config.funcs = &simpledrm_mode_config_funcs; - - ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs, - DRM_MODE_CONNECTOR_Unknown); - if (ret) - return ret; - drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs); - drm_connector_set_panel_orientation_with_quirk(connector, - DRM_MODE_PANEL_ORIENTATION_UNKNOWN, - mode->hdisplay, mode->vdisplay); - - formats = simpledrm_device_formats(sdev, &nformats); - - ret = drm_simple_display_pipe_init(dev, pipe, &simpledrm_simple_display_pipe_funcs, - formats, nformats, simpledrm_format_modifiers, - connector); - if (ret) - return ret; - - drm_plane_enable_fb_damage_clips(&pipe->plane); - - drm_mode_config_reset(dev); - - return 0; -} - -/* - * Init / Cleanup - */ - -static struct simpledrm_device * -simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev) -{ - struct simpledrm_device *sdev; - int ret; - - sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device, - dev); + sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device, dev); if (IS_ERR(sdev)) return ERR_CAST(sdev); + dev = &sdev->dev; sdev->pdev = pdev; platform_set_drvdata(pdev, sdev); + /* + * Hardware settings + */ + ret = simpledrm_device_init_clocks(sdev); if (ret) return ERR_PTR(ret); ret = simpledrm_device_init_regulators(sdev); if (ret) return ERR_PTR(ret); - ret = simpledrm_device_init_fb(sdev); + + if (pd) { + width = simplefb_get_width_pd(dev, pd); + if (width < 0) + return ERR_PTR(width); + height = simplefb_get_height_pd(dev, pd); + if (height < 0) + return ERR_PTR(height); + stride = simplefb_get_stride_pd(dev, pd); + if (stride < 0) + return ERR_PTR(stride); + format = simplefb_get_format_pd(dev, pd); + if (IS_ERR(format)) + return ERR_CAST(format); + } else if (of_node) { + width = simplefb_get_width_of(dev, of_node); + if (width < 0) + return ERR_PTR(width); + height = simplefb_get_height_of(dev, of_node); + if (height < 0) + return ERR_PTR(height); + stride = simplefb_get_stride_of(dev, of_node); + if (stride < 0) + return ERR_PTR(stride); + format = simplefb_get_format_of(dev, of_node); + if (IS_ERR(format)) + return ERR_CAST(format); + } else { + drm_err(dev, "no simplefb configuration found\n"); + return ERR_PTR(-ENODEV); + } + sdev->mode = simpledrm_mode(width, height); + sdev->format = format; + sdev->pitch = stride; + + drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sdev->mode)); + drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n", + &format->format, width, height, stride); + + /* + * Memory management + */ + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return ERR_PTR(-EINVAL); + + ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res)); + if (ret) { + drm_err(dev, "could not acquire memory range %pr: error %d\n", res, ret); + return ERR_PTR(ret); + } + + mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res), drv->name); + if (!mem) { + /* + * We cannot make this fatal. Sometimes this comes from magic + * spaces our resource handlers simply don't know about. Use + * the I/O-memory resource as-is and try to map that instead. + */ + drm_warn(dev, "could not acquire memory region %pr\n", res); + mem = res; + } + + screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem)); + if (!screen_base) + return ERR_PTR(-ENOMEM); + sdev->screen_base = screen_base; + + /* + * Modesetting + */ + + ret = drmm_mode_config_init(dev); if (ret) return ERR_PTR(ret); - ret = simpledrm_device_init_mm(sdev); + + max_width = max_t(unsigned long, width, DRM_SHADOW_PLANE_MAX_WIDTH); + max_height = max_t(unsigned long, height, DRM_SHADOW_PLANE_MAX_HEIGHT); + + dev->mode_config.min_width = width; + dev->mode_config.max_width = max_width; + dev->mode_config.min_height = height; + dev->mode_config.max_height = max_height; + dev->mode_config.preferred_depth = format->cpp[0] * 8; + dev->mode_config.funcs = &simpledrm_mode_config_funcs; + + connector = &sdev->connector; + ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs, + DRM_MODE_CONNECTOR_Unknown); if (ret) return ERR_PTR(ret); - ret = simpledrm_device_init_modeset(sdev); + drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs); + drm_connector_set_panel_orientation_with_quirk(connector, + DRM_MODE_PANEL_ORIENTATION_UNKNOWN, + width, height); + + formats = simpledrm_device_formats(sdev, &nformats); + + pipe = &sdev->pipe; + ret = drm_simple_display_pipe_init(dev, pipe, &simpledrm_simple_display_pipe_funcs, + formats, nformats, simpledrm_format_modifiers, + connector); if (ret) return ERR_PTR(ret); + drm_plane_enable_fb_damage_clips(&pipe->plane); + + drm_mode_config_reset(dev); + return sdev; } From 802fd5750faca181cade177642e0e5233ff25f85 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 1 Aug 2022 15:50:26 +0200 Subject: [PATCH 250/396] drm/simpledrm: Remove pdev field from device structure Replace the remaining uses of the field pdev by upcasts from the Linux device and remove the field. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220801135028.30647-4-tzimmermann@suse.de --- drivers/gpu/drm/tiny/simpledrm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index f458e8bec63e..9d27608d7369 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -198,7 +198,6 @@ simplefb_get_format_of(struct drm_device *dev, struct device_node *of_node) struct simpledrm_device { struct drm_device dev; - struct platform_device *pdev; /* clocks */ #if defined CONFIG_OF && defined CONFIG_COMMON_CLK @@ -271,7 +270,7 @@ static void simpledrm_device_release_clocks(void *res) static int simpledrm_device_init_clocks(struct simpledrm_device *sdev) { struct drm_device *dev = &sdev->dev; - struct platform_device *pdev = sdev->pdev; + struct platform_device *pdev = to_platform_device(dev->dev); struct device_node *of_node = pdev->dev.of_node; struct clk *clock; unsigned int i; @@ -369,7 +368,7 @@ static void simpledrm_device_release_regulators(void *res) static int simpledrm_device_init_regulators(struct simpledrm_device *sdev) { struct drm_device *dev = &sdev->dev; - struct platform_device *pdev = sdev->pdev; + struct platform_device *pdev = to_platform_device(dev->dev); struct device_node *of_node = pdev->dev.of_node; struct property *prop; struct regulator *regulator; @@ -701,7 +700,6 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, if (IS_ERR(sdev)) return ERR_CAST(sdev); dev = &sdev->dev; - sdev->pdev = pdev; platform_set_drvdata(pdev, sdev); /* From fd9e3169e42b7b9e3a5c58ca2bc95a15f9de1d6c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 1 Aug 2022 15:50:27 +0200 Subject: [PATCH 251/396] drm/simpledrm: Compute framebuffer stride if not set Compute the framebuffer's scanline stride length if not given by the simplefb data. v3: * get pixel size from drm_format_info_bpp() (Geert, Javier) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220801135028.30647-5-tzimmermann@suse.de --- drivers/gpu/drm/tiny/simpledrm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 9d27608d7369..11a7348ccf4d 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -743,6 +743,9 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, drm_err(dev, "no simplefb configuration found\n"); return ERR_PTR(-ENODEV); } + if (!stride) + stride = DIV_ROUND_UP(drm_format_info_bpp(format, 0) * width, 8); + sdev->mode = simpledrm_mode(width, height); sdev->format = format; sdev->pitch = stride; From de40c281fe0b6babf3d1a25e034525a23e125d0c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 1 Aug 2022 15:50:28 +0200 Subject: [PATCH 252/396] drm/simpledrm: Convert to atomic helpers Replace the simple-KMS helpers with the regular atomic helpers. The regular helpers are better architectured and therefore allow for easier code sharing among drivers. No functional changes. v3: * remove empty CRTC helpers atomic_{enable, disable} (Javier) * unconditionally run drm_atomic_helper_check_plane_state() Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220801135028.30647-6-tzimmermann@suse.de --- drivers/gpu/drm/tiny/simpledrm.c | 309 +++++++++++++++++++------------ 1 file changed, 186 insertions(+), 123 deletions(-) diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 11a7348ccf4d..82fd98f77981 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -8,6 +8,7 @@ #include <linux/regulator/consumer.h> #include <drm/drm_aperture.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> @@ -20,8 +21,8 @@ #include <drm/drm_gem_shmem_helper.h> #include <drm/drm_managed.h> #include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #define DRIVER_NAME "simpledrm" #define DRIVER_DESC "DRM driver for simple-framebuffer platform devices" @@ -221,8 +222,10 @@ struct simpledrm_device { /* modesetting */ uint32_t formats[8]; size_t nformats; + struct drm_plane primary_plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector connector; - struct drm_simple_display_pipe pipe; }; static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev) @@ -460,7 +463,7 @@ static int simpledrm_device_init_regulators(struct simpledrm_device *sdev) * TODO: Add blit helpers for remaining formats and uncomment * constants. */ -static const uint32_t simpledrm_default_formats[] = { +static const uint32_t simpledrm_primary_plane_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, @@ -471,11 +474,149 @@ static const uint32_t simpledrm_default_formats[] = { DRM_FORMAT_ARGB2101010, }; -static const uint64_t simpledrm_format_modifiers[] = { +static const uint64_t simpledrm_primary_plane_format_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID }; +static int simpledrm_primary_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *new_state) +{ + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); + struct drm_crtc *new_crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = NULL; + int ret; + + if (new_crtc) + new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc); + + ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + else if (!new_plane_state->visible) + return 0; + + return 0; +} + +static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *old_state) +{ + struct drm_plane_state *plane_state = plane->state; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane); + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ + struct drm_framebuffer *fb = plane_state->fb; + struct drm_device *dev = plane->dev; + struct simpledrm_device *sdev = simpledrm_device_of_dev(dev); + void __iomem *dst = sdev->screen_base; + struct drm_rect src_clip, dst_clip; + int idx; + + if (!fb) + return; + + if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip)) + return; + + dst_clip = plane_state->dst; + if (!drm_rect_intersect(&dst_clip, &src_clip)) + return; + + if (!drm_dev_enter(dev, &idx)) + return; + + dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip); + drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip); + + drm_dev_exit(idx); +} + +static void simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *old_state) +{ + struct drm_device *dev = plane->dev; + struct simpledrm_device *sdev = simpledrm_device_of_dev(dev); + int idx; + + if (!drm_dev_enter(dev, &idx)) + return; + + /* Clear screen to black if disabled */ + memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay); + + drm_dev_exit(idx); +} + +static const struct drm_plane_helper_funcs simpledrm_primary_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = simpledrm_primary_plane_helper_atomic_check, + .atomic_update = simpledrm_primary_plane_helper_atomic_update, + .atomic_disable = simpledrm_primary_plane_helper_atomic_disable, +}; + +static const struct drm_plane_funcs simpledrm_primary_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) +{ + struct simpledrm_device *sdev = simpledrm_device_of_dev(crtc->dev); + + if (mode->hdisplay != sdev->mode.hdisplay && + mode->vdisplay != sdev->mode.vdisplay) + return MODE_ONE_SIZE; + else if (mode->hdisplay != sdev->mode.hdisplay) + return MODE_ONE_WIDTH; + else if (mode->vdisplay != sdev->mode.vdisplay) + return MODE_ONE_HEIGHT; + + return MODE_OK; +} + +static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + int ret; + + ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false); + if (ret) + return ret; + + return drm_atomic_add_affected_planes(new_state, crtc); +} + +/* + * The CRTC is always enabled. Screen updates are performed by + * the primary plane's atomic_update function. Disabling clears + * the screen in the primary plane's atomic_disable function. + */ +static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs = { + .mode_valid = simpledrm_crtc_helper_mode_valid, + .atomic_check = simpledrm_crtc_helper_atomic_check, +}; + +static const struct drm_crtc_funcs simpledrm_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs simpledrm_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + static int simpledrm_connector_helper_get_modes(struct drm_connector *connector) { struct simpledrm_device *sdev = simpledrm_device_of_dev(connector->dev); @@ -511,113 +652,6 @@ static const struct drm_connector_funcs simpledrm_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static enum drm_mode_status -simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) -{ - struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev); - - if (mode->hdisplay != sdev->mode.hdisplay && - mode->vdisplay != sdev->mode.vdisplay) - return MODE_ONE_SIZE; - else if (mode->hdisplay != sdev->mode.hdisplay) - return MODE_ONE_WIDTH; - else if (mode->vdisplay != sdev->mode.vdisplay) - return MODE_ONE_HEIGHT; - - return MODE_OK; -} - -static void -simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) -{ - struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev); - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - struct drm_framebuffer *fb = plane_state->fb; - void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ - struct drm_device *dev = &sdev->dev; - void __iomem *dst = sdev->screen_base; - struct drm_rect src_clip, dst_clip; - int idx; - - if (!fb) - return; - - drm_rect_fp_to_int(&src_clip, &plane_state->src); - - dst_clip = plane_state->dst; - if (!drm_rect_intersect(&dst_clip, &src_clip)) - return; - - if (!drm_dev_enter(dev, &idx)) - return; - - dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip); - drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip); - - drm_dev_exit(idx); -} - -static void -simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) -{ - struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev); - struct drm_device *dev = &sdev->dev; - int idx; - - if (!drm_dev_enter(dev, &idx)) - return; - - /* Clear screen to black if disabled */ - memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay); - - drm_dev_exit(idx); -} - -static void -simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_plane_state) -{ - struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev); - struct drm_plane_state *plane_state = pipe->plane.state; - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ - struct drm_framebuffer *fb = plane_state->fb; - struct drm_device *dev = &sdev->dev; - void __iomem *dst = sdev->screen_base; - struct drm_rect src_clip, dst_clip; - int idx; - - if (!fb) - return; - - if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip)) - return; - - dst_clip = plane_state->dst; - if (!drm_rect_intersect(&dst_clip, &src_clip)) - return; - - if (!drm_dev_enter(dev, &idx)) - return; - - dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip); - drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip); - - drm_dev_exit(idx); -} - -static const struct drm_simple_display_pipe_funcs -simpledrm_simple_display_pipe_funcs = { - .mode_valid = simpledrm_simple_display_pipe_mode_valid, - .enable = simpledrm_simple_display_pipe_enable, - .disable = simpledrm_simple_display_pipe_disable, - .update = simpledrm_simple_display_pipe_update, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, -}; - static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = { .fb_create = drm_gem_fb_create_with_dirty, .atomic_check = drm_atomic_helper_check, @@ -653,10 +687,10 @@ static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev, sdev->nformats = 1; /* default formats go second */ - for (i = 0; i < ARRAY_SIZE(simpledrm_default_formats); ++i) { - if (simpledrm_default_formats[i] == sdev->format->format) + for (i = 0; i < ARRAY_SIZE(simpledrm_primary_plane_formats); ++i) { + if (simpledrm_primary_plane_formats[i] == sdev->format->format) continue; /* native format already went first */ - sdev->formats[sdev->nformats] = simpledrm_default_formats[i]; + sdev->formats[sdev->nformats] = simpledrm_primary_plane_formats[i]; sdev->nformats++; } @@ -689,8 +723,10 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, const struct drm_format_info *format; struct resource *res, *mem; void __iomem *screen_base; + struct drm_plane *primary_plane; + struct drm_crtc *crtc; + struct drm_encoder *encoder; struct drm_connector *connector; - struct drm_simple_display_pipe *pipe; unsigned long max_width, max_height; const uint32_t *formats; size_t nformats; @@ -802,6 +838,40 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, dev->mode_config.preferred_depth = format->cpp[0] * 8; dev->mode_config.funcs = &simpledrm_mode_config_funcs; + /* Primary plane */ + + formats = simpledrm_device_formats(sdev, &nformats); + + primary_plane = &sdev->primary_plane; + ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs, + formats, nformats, + simpledrm_primary_plane_format_modifiers, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ERR_PTR(ret); + drm_plane_helper_add(primary_plane, &simpledrm_primary_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(primary_plane); + + /* CRTC */ + + crtc = &sdev->crtc; + ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, + &simpledrm_crtc_funcs, NULL); + if (ret) + return ERR_PTR(ret); + drm_crtc_helper_add(crtc, &simpledrm_crtc_helper_funcs); + + /* Encoder */ + + encoder = &sdev->encoder; + ret = drm_encoder_init(dev, encoder, &simpledrm_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ERR_PTR(ret); + encoder->possible_crtcs = drm_crtc_mask(crtc); + + /* Connector */ + connector = &sdev->connector; ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs, DRM_MODE_CONNECTOR_Unknown); @@ -812,17 +882,10 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, DRM_MODE_PANEL_ORIENTATION_UNKNOWN, width, height); - formats = simpledrm_device_formats(sdev, &nformats); - - pipe = &sdev->pipe; - ret = drm_simple_display_pipe_init(dev, pipe, &simpledrm_simple_display_pipe_funcs, - formats, nformats, simpledrm_format_modifiers, - connector); + ret = drm_connector_attach_encoder(connector, encoder); if (ret) return ERR_PTR(ret); - drm_plane_enable_fb_damage_clips(&pipe->plane); - drm_mode_config_reset(dev); return sdev; From ef8886f321c5dab8124b9153d25afa2a71d05323 Mon Sep 17 00:00:00 2001 From: Zeng Jingxiang <linuszeng@tencent.com> Date: Wed, 27 Jul 2022 15:31:19 +0800 Subject: [PATCH 253/396] gpu: lontium-lt9611: Fix NULL pointer dereference in lt9611_connector_init() A NULL check for bridge->encoder shows that it may be NULL, but it already been dereferenced on all paths leading to the check. 812 if (!bridge->encoder) { Dereference the pointer bridge->encoder. 810 drm_connector_attach_encoder(<9611->connector, bridge->encoder); Signed-off-by: Zeng Jingxiang <linuszeng@tencent.com> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220727073119.1578972-1-zengjx95@gmail.com --- drivers/gpu/drm/bridge/lontium-lt9611.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index 8a60e83482a0..5fccacc159f0 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -813,13 +813,14 @@ static int lt9611_connector_init(struct drm_bridge *bridge, struct lt9611 *lt961 drm_connector_helper_add(<9611->connector, <9611_bridge_connector_helper_funcs); - drm_connector_attach_encoder(<9611->connector, bridge->encoder); if (!bridge->encoder) { DRM_ERROR("Parent encoder object not found"); return -ENODEV; } + drm_connector_attach_encoder(<9611->connector, bridge->encoder); + return 0; } From 6a3aaa2bc03ea7ecb93741d2f55aa9064e95d528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Larumbe?= <adrian.larumbe@collabora.com> Date: Fri, 29 Jul 2022 15:46:09 +0100 Subject: [PATCH 254/396] drm/panfrost: Add specific register offset macros for JS and MMU AS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each Panfrost job has its own job slot and MMU address space set of registers, which are selected with a job-specific index. Turn the shift and stride used for selection of the right register set base into a define rather than using magic numbers. Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220729144610.2105223-2-adrian.larumbe@collabora.com --- drivers/gpu/drm/panfrost/panfrost_regs.h | 42 ++++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h index accb4fa3adb8..919f44ac853d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_regs.h +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h @@ -226,23 +226,25 @@ #define JOB_INT_MASK_DONE(j) BIT(j) #define JS_BASE 0x1800 -#define JS_HEAD_LO(n) (JS_BASE + ((n) * 0x80) + 0x00) -#define JS_HEAD_HI(n) (JS_BASE + ((n) * 0x80) + 0x04) -#define JS_TAIL_LO(n) (JS_BASE + ((n) * 0x80) + 0x08) -#define JS_TAIL_HI(n) (JS_BASE + ((n) * 0x80) + 0x0c) -#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * 0x80) + 0x10) -#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * 0x80) + 0x14) -#define JS_CONFIG(n) (JS_BASE + ((n) * 0x80) + 0x18) -#define JS_XAFFINITY(n) (JS_BASE + ((n) * 0x80) + 0x1c) -#define JS_COMMAND(n) (JS_BASE + ((n) * 0x80) + 0x20) -#define JS_STATUS(n) (JS_BASE + ((n) * 0x80) + 0x24) -#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x40) -#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x44) -#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * 0x80) + 0x50) -#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * 0x80) + 0x54) -#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x58) -#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x60) -#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * 0x80) + 0x70) +#define JS_SLOT_STRIDE 0x80 + +#define JS_HEAD_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x00) +#define JS_HEAD_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x04) +#define JS_TAIL_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x08) +#define JS_TAIL_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x0c) +#define JS_AFFINITY_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x10) +#define JS_AFFINITY_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x14) +#define JS_CONFIG(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x18) +#define JS_XAFFINITY(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x1c) +#define JS_COMMAND(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x20) +#define JS_STATUS(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x24) +#define JS_HEAD_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x40) +#define JS_HEAD_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x44) +#define JS_AFFINITY_NEXT_LO(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x50) +#define JS_AFFINITY_NEXT_HI(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x54) +#define JS_CONFIG_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x58) +#define JS_COMMAND_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x60) +#define JS_FLUSH_ID_NEXT(n) (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x70) /* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */ #define JS_CONFIG_START_FLUSH_CLEAN BIT(8) @@ -281,7 +283,9 @@ #define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then flush all L2 caches then issue a flush region command to all MMUs */ -#define MMU_AS(as) (0x2400 + ((as) << 6)) +#define MMU_BASE 0x2400 +#define MMU_AS_SHIFT 0x06 +#define MMU_AS(as) (MMU_BASE + ((as) << MMU_AS_SHIFT)) #define AS_TRANSTAB_LO(as) (MMU_AS(as) + 0x00) /* (RW) Translation Table Base Address for address space n, low word */ #define AS_TRANSTAB_HI(as) (MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */ @@ -300,6 +304,8 @@ #define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */ #define AS_FAULTEXTRA_HI(as) (MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */ +#define MMU_AS_STRIDE (1 << MMU_AS_SHIFT) + /* * Begin LPAE MMU TRANSTAB register values */ From 730c2bf4ad395acf0aa0820535fdb8ea6abe5df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Larumbe?= <adrian.larumbe@collabora.com> Date: Fri, 29 Jul 2022 15:46:10 +0100 Subject: [PATCH 255/396] drm/panfrost: Add support for devcoredump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the event of a job timeout, debug dump information will be written into /sys/class/devcoredump. Inspired by etnaviv's similar feature. Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220729144610.2105223-3-adrian.larumbe@collabora.com --- drivers/gpu/drm/panfrost/Kconfig | 1 + drivers/gpu/drm/panfrost/Makefile | 3 +- drivers/gpu/drm/panfrost/panfrost_dump.c | 249 +++++++++++++++++++++++ drivers/gpu/drm/panfrost/panfrost_dump.h | 12 ++ drivers/gpu/drm/panfrost/panfrost_job.c | 3 + include/uapi/drm/panfrost_drm.h | 47 +++++ 6 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.c create mode 100644 drivers/gpu/drm/panfrost/panfrost_dump.h diff --git a/drivers/gpu/drm/panfrost/Kconfig b/drivers/gpu/drm/panfrost/Kconfig index 86cdc0ce79e6..079600328be1 100644 --- a/drivers/gpu/drm/panfrost/Kconfig +++ b/drivers/gpu/drm/panfrost/Kconfig @@ -11,6 +11,7 @@ config DRM_PANFROST select DRM_GEM_SHMEM_HELPER select PM_DEVFREQ select DEVFREQ_GOV_SIMPLE_ONDEMAND + select WANT_DEV_COREDUMP help DRM driver for ARM Mali Midgard (T6xx, T7xx, T8xx) and Bifrost (G3x, G5x, G7x) GPUs. diff --git a/drivers/gpu/drm/panfrost/Makefile b/drivers/gpu/drm/panfrost/Makefile index b71935862417..7da2b3f02ed9 100644 --- a/drivers/gpu/drm/panfrost/Makefile +++ b/drivers/gpu/drm/panfrost/Makefile @@ -9,6 +9,7 @@ panfrost-y := \ panfrost_gpu.o \ panfrost_job.o \ panfrost_mmu.o \ - panfrost_perfcnt.o + panfrost_perfcnt.o \ + panfrost_dump.o obj-$(CONFIG_DRM_PANFROST) += panfrost.o diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.c b/drivers/gpu/drm/panfrost/panfrost_dump.c new file mode 100644 index 000000000000..89056a1aac7d --- /dev/null +++ b/drivers/gpu/drm/panfrost/panfrost_dump.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2021 Collabora ltd. */ + +#include <linux/err.h> +#include <linux/device.h> +#include <linux/devcoredump.h> +#include <linux/moduleparam.h> +#include <linux/iosys-map.h> +#include <drm/panfrost_drm.h> +#include <drm/drm_device.h> + +#include "panfrost_job.h" +#include "panfrost_gem.h" +#include "panfrost_regs.h" +#include "panfrost_dump.h" +#include "panfrost_device.h" + +static bool panfrost_dump_core = true; +module_param_named(dump_core, panfrost_dump_core, bool, 0600); + +struct panfrost_dump_iterator { + void *start; + struct panfrost_dump_object_header *hdr; + void *data; +}; + +static const unsigned short panfrost_dump_registers[] = { + SHADER_READY_LO, + SHADER_READY_HI, + TILER_READY_LO, + TILER_READY_HI, + L2_READY_LO, + L2_READY_HI, + JOB_INT_MASK, + JOB_INT_STAT, + JS_HEAD_LO(0), + JS_HEAD_HI(0), + JS_TAIL_LO(0), + JS_TAIL_HI(0), + JS_AFFINITY_LO(0), + JS_AFFINITY_HI(0), + JS_CONFIG(0), + JS_STATUS(0), + JS_HEAD_NEXT_LO(0), + JS_HEAD_NEXT_HI(0), + JS_AFFINITY_NEXT_LO(0), + JS_AFFINITY_NEXT_HI(0), + JS_CONFIG_NEXT(0), + MMU_INT_MASK, + MMU_INT_STAT, + AS_TRANSTAB_LO(0), + AS_TRANSTAB_HI(0), + AS_MEMATTR_LO(0), + AS_MEMATTR_HI(0), + AS_FAULTSTATUS(0), + AS_FAULTADDRESS_LO(0), + AS_FAULTADDRESS_HI(0), + AS_STATUS(0), +}; + +static void panfrost_core_dump_header(struct panfrost_dump_iterator *iter, + u32 type, void *data_end) +{ + struct panfrost_dump_object_header *hdr = iter->hdr; + + hdr->magic = cpu_to_le32(PANFROSTDUMP_MAGIC); + hdr->type = cpu_to_le32(type); + hdr->file_offset = cpu_to_le32(iter->data - iter->start); + hdr->file_size = cpu_to_le32(data_end - iter->data); + + iter->hdr++; + iter->data += le32_to_cpu(hdr->file_size); +} + +static void +panfrost_core_dump_registers(struct panfrost_dump_iterator *iter, + struct panfrost_device *pfdev, + u32 as_nr, int slot) +{ + struct panfrost_dump_registers *dumpreg = iter->data; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(panfrost_dump_registers); i++, dumpreg++) { + unsigned int js_as_offset = 0; + unsigned int reg; + + if (panfrost_dump_registers[i] >= JS_BASE && + panfrost_dump_registers[i] <= JS_BASE + JS_SLOT_STRIDE) + js_as_offset = slot * JS_SLOT_STRIDE; + else if (panfrost_dump_registers[i] >= MMU_BASE && + panfrost_dump_registers[i] <= MMU_BASE + MMU_AS_STRIDE) + js_as_offset = (as_nr << MMU_AS_SHIFT); + + reg = panfrost_dump_registers[i] + js_as_offset; + + dumpreg->reg = cpu_to_le32(reg); + dumpreg->value = cpu_to_le32(gpu_read(pfdev, reg)); + } + + panfrost_core_dump_header(iter, PANFROSTDUMP_BUF_REG, dumpreg); +} + +void panfrost_core_dump(struct panfrost_job *job) +{ + struct panfrost_device *pfdev = job->pfdev; + struct panfrost_dump_iterator iter; + struct drm_gem_object *dbo; + unsigned int n_obj, n_bomap_pages; + __le64 *bomap, *bomap_start; + size_t file_size; + u32 as_nr; + int slot; + int ret, i; + + as_nr = job->mmu->as; + slot = panfrost_job_get_slot(job); + + /* Only catch the first event, or when manually re-armed */ + if (!panfrost_dump_core) + return; + panfrost_dump_core = false; + + /* At least, we dump registers and end marker */ + n_obj = 2; + n_bomap_pages = 0; + file_size = ARRAY_SIZE(panfrost_dump_registers) * + sizeof(struct panfrost_dump_registers); + + /* Add in the active buffer objects */ + for (i = 0; i < job->bo_count; i++) { + /* + * Even though the CPU could be configured to use 16K or 64K pages, this + * is a very unusual situation for most kernel setups on SoCs that have + * a Panfrost device. Also many places across the driver make the somewhat + * arbitrary assumption that Panfrost's MMU page size is the same as the CPU's, + * so let's have a sanity check to ensure that's always the case + */ + dbo = job->bos[i]; + WARN_ON(!IS_ALIGNED(dbo->size, PAGE_SIZE)); + + file_size += dbo->size; + n_bomap_pages += dbo->size >> PAGE_SHIFT; + n_obj++; + } + + /* If we have any buffer objects, add a bomap object */ + if (n_bomap_pages) { + file_size += n_bomap_pages * sizeof(*bomap); + n_obj++; + } + + /* Add the size of the headers */ + file_size += sizeof(*iter.hdr) * n_obj; + + /* + * Allocate the file in vmalloc memory, it's likely to be big. + * The reason behind these GFP flags is that we don't want to trigger the + * OOM killer in the event that not enough memory could be found for our + * dump file. We also don't want the allocator to do any error reporting, + * as the right behaviour is failing gracefully if a big enough buffer + * could not be allocated. + */ + iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN | + __GFP_NORETRY); + if (!iter.start) { + dev_warn(pfdev->dev, "failed to allocate devcoredump file\n"); + return; + } + + /* Point the data member after the headers */ + iter.hdr = iter.start; + iter.data = &iter.hdr[n_obj]; + + memset(iter.hdr, 0, iter.data - iter.start); + + /* + * For now, we write the job identifier in the register dump header, + * so that we can decode the entire dump later with pandecode + */ + iter.hdr->reghdr.jc = cpu_to_le64(job->jc); + iter.hdr->reghdr.major = cpu_to_le32(PANFROSTDUMP_MAJOR); + iter.hdr->reghdr.minor = cpu_to_le32(PANFROSTDUMP_MINOR); + iter.hdr->reghdr.gpu_id = cpu_to_le32(pfdev->features.id); + iter.hdr->reghdr.nbos = cpu_to_le64(job->bo_count); + + panfrost_core_dump_registers(&iter, pfdev, as_nr, slot); + + /* Reserve space for the bomap */ + if (job->bo_count) { + bomap_start = bomap = iter.data; + memset(bomap, 0, sizeof(*bomap) * n_bomap_pages); + panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BOMAP, + bomap + n_bomap_pages); + } + + for (i = 0; i < job->bo_count; i++) { + struct iosys_map map; + struct panfrost_gem_mapping *mapping; + struct panfrost_gem_object *bo; + struct sg_page_iter page_iter; + void *vaddr; + + bo = to_panfrost_bo(job->bos[i]); + mapping = job->mappings[i]; + + if (!bo->base.sgt) { + dev_err(pfdev->dev, "Panfrost Dump: BO has no sgt, cannot dump\n"); + iter.hdr->bomap.valid = 0; + goto dump_header; + } + + ret = drm_gem_shmem_vmap(&bo->base, &map); + if (ret) { + dev_err(pfdev->dev, "Panfrost Dump: couldn't map Buffer Object\n"); + iter.hdr->bomap.valid = 0; + goto dump_header; + } + + WARN_ON(!mapping->active); + + iter.hdr->bomap.data[0] = cpu_to_le32((bomap - bomap_start)); + + for_each_sgtable_page(bo->base.sgt, &page_iter, 0) { + struct page *page = sg_page_iter_page(&page_iter); + + if (!IS_ERR(page)) { + *bomap++ = cpu_to_le64(page_to_phys(page)); + } else { + dev_err(pfdev->dev, "Panfrost Dump: wrong page\n"); + *bomap++ = ~cpu_to_le64(0); + } + } + + iter.hdr->bomap.iova = cpu_to_le64(mapping->mmnode.start << PAGE_SHIFT); + + vaddr = map.vaddr; + memcpy(iter.data, vaddr, bo->base.base.size); + + drm_gem_shmem_vunmap(&bo->base, &map); + + iter.hdr->bomap.valid = cpu_to_le32(1); + +dump_header: panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BO, iter.data + + bo->base.base.size); + } + panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_TRAILER, iter.data); + + dev_coredumpv(pfdev->dev, iter.start, iter.data - iter.start, GFP_KERNEL); +} diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.h b/drivers/gpu/drm/panfrost/panfrost_dump.h new file mode 100644 index 000000000000..7d9bcefa5346 --- /dev/null +++ b/drivers/gpu/drm/panfrost/panfrost_dump.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2021 Collabora ltd. + */ + +#ifndef PANFROST_DUMP_H +#define PANFROST_DUMP_H + +struct panfrost_job; +void panfrost_core_dump(struct panfrost_job *job); + +#endif diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 7c4208476fbd..dbc597ab46fb 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -20,6 +20,7 @@ #include "panfrost_regs.h" #include "panfrost_gpu.h" #include "panfrost_mmu.h" +#include "panfrost_dump.h" #define JOB_TIMEOUT_MS 500 @@ -727,6 +728,8 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job job_read(pfdev, JS_TAIL_LO(js)), sched_job); + panfrost_core_dump(job); + atomic_set(&pfdev->reset.pending, 1); panfrost_reset(pfdev, sched_job); diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h index 9e40277d8185..eac87310b348 100644 --- a/include/uapi/drm/panfrost_drm.h +++ b/include/uapi/drm/panfrost_drm.h @@ -224,6 +224,53 @@ struct drm_panfrost_madvise { __u32 retained; /* out, whether backing store still exists */ }; +/* Definitions for coredump decoding in user space */ +#define PANFROSTDUMP_MAJOR 1 +#define PANFROSTDUMP_MINOR 0 + +#define PANFROSTDUMP_MAGIC 0x464E4150 /* PANF */ + +#define PANFROSTDUMP_BUF_REG 0 +#define PANFROSTDUMP_BUF_BOMAP (PANFROSTDUMP_BUF_REG + 1) +#define PANFROSTDUMP_BUF_BO (PANFROSTDUMP_BUF_BOMAP + 1) +#define PANFROSTDUMP_BUF_TRAILER (PANFROSTDUMP_BUF_BO + 1) + +struct panfrost_dump_object_header { + __le32 magic; + __le32 type; + __le32 file_size; + __le32 file_offset; + + union { + struct pan_reg_hdr { + __le64 jc; + __le32 gpu_id; + __le32 major; + __le32 minor; + __le64 nbos; + } reghdr; + + struct pan_bomap_hdr { + __le32 valid; + __le64 iova; + __le32 data[2]; + } bomap; + + /* + * Force same size in case we want to expand the header + * with new fields and also keep it 512-byte aligned + */ + + __le32 sizer[496]; + }; +}; + +/* Registers object, an array of these */ +struct panfrost_dump_registers { + __le32 reg; + __le32 value; +}; + #if defined(__cplusplus) } #endif From 116d902fa9ff1f559b66bafad0f0cad90df95d21 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:53:53 +0200 Subject: [PATCH 256/396] iosys-map: Add IOSYS_MAP_INIT_VADDR_IOMEM() Add IOSYS_MAP_INIT_VADDR_IOMEM() for static init of variables of type struct iosys_map. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-2-tzimmermann@suse.de --- include/linux/iosys-map.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h index a533cae189d7..cb71aa616bd3 100644 --- a/include/linux/iosys-map.h +++ b/include/linux/iosys-map.h @@ -46,10 +46,13 @@ * * iosys_map_set_vaddr(&map, 0xdeadbeaf); * - * To set an address in I/O memory, use iosys_map_set_vaddr_iomem(). + * To set an address in I/O memory, use IOSYS_MAP_INIT_VADDR_IOMEM() or + * iosys_map_set_vaddr_iomem(). * * .. code-block:: c * + * struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(0xdeadbeaf); + * * iosys_map_set_vaddr_iomem(&map, 0xdeadbeaf); * * Instances of struct iosys_map do not have to be cleaned up, but @@ -121,6 +124,16 @@ struct iosys_map { .is_iomem = false, \ } +/** + * IOSYS_MAP_INIT_VADDR_IOMEM - Initializes struct iosys_map to an address in I/O memory + * @vaddr_iomem_: An I/O-memory address + */ +#define IOSYS_MAP_INIT_VADDR_IOMEM(vaddr_iomem_) \ + { \ + .vaddr_iomem = (vaddr_iomem_), \ + .is_iomem = true, \ + } + /** * IOSYS_MAP_INIT_OFFSET - Initializes struct iosys_map from another iosys_map * @map_: The dma-buf mapping structure to copy from From 71bf55872cbe035820a87b2aa5fc1dc60678abfa Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:53:54 +0200 Subject: [PATCH 257/396] drm/format-helper: Provide drm_fb_blit() Provide drm_fb_blit() that works with struct iosys_map. Update all users of drm_fb_blit_toio(), which required a destination buffer in I/O memory. This patch only updates the function's interface. The implementation still relies on the destination buffer to be located in I/O memory. See the follow-up patches for implementational changes. The new function's interface works with multi-plane color formats, but again implementation only supports a single plane for now. v2: * rebase onto refactored simpledrm * use IOSYS_MAP_INIT_VADDR() (Sam) * update the commit message on the use of I/O memory (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 44 ++++++++++++++++++----------- drivers/gpu/drm/tiny/simpledrm.c | 8 +++--- include/drm/drm_format_helper.h | 7 +++-- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 400b16d9147d..07f329f607a3 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -8,9 +8,10 @@ * (at your option) any later version. */ +#include <linux/io.h> +#include <linux/iosys-map.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/io.h> #include <drm/drm_device.h> #include <drm/drm_format_helper.h> @@ -545,9 +546,10 @@ void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vad EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); /** - * drm_fb_blit_toio - Copy parts of a framebuffer to display memory - * @dst: The display memory to copy to - * @dst_pitch: Number of bytes between two consecutive scanlines within dst + * drm_fb_blit - Copy parts of a framebuffer to display memory + * @dst: Array of display-memory addresses to copy to + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. * @dst_format: FOURCC code of the display's color format * @vmap: The framebuffer memory to copy from * @fb: The framebuffer to copy from @@ -555,16 +557,22 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); * * This function copies parts of a framebuffer to display memory. If the * formats of the display and the framebuffer mismatch, the blit function - * will attempt to convert between them. + * will attempt to convert between them during the process. The parameters @dst, + * @dst_pitch and @vmap refer to arrays. Each array must have at least as many + * entries as there are planes in @dst_format's format. Each entry stores the + * value for the format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). * * Returns: * 0 on success, or * -EINVAL if the color-format conversion failed, or * a negative error code otherwise. */ -int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_format, - const void *vmap, const struct drm_framebuffer *fb, - const struct drm_rect *clip) +int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { uint32_t fb_format = fb->format->format; @@ -579,30 +587,35 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for dst_format = DRM_FORMAT_XRGB2101010; if (dst_format == fb_format) { - drm_fb_memcpy_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_memcpy_toio(dst[0].vaddr_iomem, dst_pitch[0], vmap[0].vaddr, fb, clip); return 0; } else if (dst_format == DRM_FORMAT_RGB565) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb565_toio(dst, dst_pitch, vmap, fb, clip, false); + drm_fb_xrgb8888_to_rgb565_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip, false); return 0; } } else if (dst_format == DRM_FORMAT_RGB888) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb888_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_xrgb8888_to_rgb888_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB8888) { if (fb_format == DRM_FORMAT_RGB888) { - drm_fb_rgb888_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_rgb888_to_xrgb8888_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip); return 0; } else if (fb_format == DRM_FORMAT_RGB565) { - drm_fb_rgb565_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_rgb565_to_xrgb8888_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB2101010) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_xrgb2101010_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_xrgb8888_to_xrgb2101010_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip); return 0; } } @@ -612,8 +625,7 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for return -EINVAL; } -EXPORT_SYMBOL(drm_fb_blit_toio); - +EXPORT_SYMBOL(drm_fb_blit); static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels) { diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 82fd98f77981..a81f91814595 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -508,11 +508,10 @@ static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane struct drm_plane_state *plane_state = plane->state; struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ struct drm_framebuffer *fb = plane_state->fb; struct drm_device *dev = plane->dev; struct simpledrm_device *sdev = simpledrm_device_of_dev(dev); - void __iomem *dst = sdev->screen_base; + struct iosys_map dst = IOSYS_MAP_INIT_VADDR(sdev->screen_base); struct drm_rect src_clip, dst_clip; int idx; @@ -529,8 +528,9 @@ static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane if (!drm_dev_enter(dev, &idx)) return; - dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip); - drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip); + iosys_map_incr(&dst, drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip)); + drm_fb_blit(&dst, &sdev->pitch, sdev->format->format, shadow_plane_state->data, fb, + &src_clip); drm_dev_exit(idx); } diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 55145eca0782..21daea7fda99 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -6,6 +6,7 @@ #ifndef __LINUX_DRM_FORMAT_HELPER_H #define __LINUX_DRM_FORMAT_HELPER_H +struct iosys_map; struct drm_format_info; struct drm_framebuffer; struct drm_rect; @@ -39,9 +40,9 @@ void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst, unsigned int dst_pit void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, const struct drm_framebuffer *fb, const struct drm_rect *clip); -int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_format, - const void *vmap, const struct drm_framebuffer *fb, - const struct drm_rect *rect); +int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *rect); void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); From edbe262acf92c986ad9a1f594ae3b4f3d3373133 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:53:55 +0200 Subject: [PATCH 258/396] drm/format-helper: Merge drm_fb_memcpy() and drm_fb_memcpy_toio() Merge drm_fb_memcpy() and drm_fb_memcpy_toio() into a drm_fb_memcpy() that uses struct iosys_map for buffers. The new function also supports multi-plane color formats. Convert all users of the original helpers. v2: * rebase onto refactored mgag200 * use drm_formap_info_bpp() (Sam) * do static init in hyperv and mgag200 (Sam) * update documentation (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-4-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 88 ++++++++++----------- drivers/gpu/drm/drm_mipi_dbi.c | 3 +- drivers/gpu/drm/gud/gud_pipe.c | 4 +- drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 9 +-- drivers/gpu/drm/mgag200/mgag200_mode.c | 9 +-- drivers/gpu/drm/tiny/cirrus.c | 21 ++--- include/drm/drm_format_helper.h | 7 +- 7 files changed, 69 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 07f329f607a3..7489c665a47c 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -131,64 +131,58 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned /** * drm_fb_memcpy - Copy clip buffer - * @dst: Destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: Source buffer + * @dst: Array of destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * - * This function does not apply clipping on dst, i.e. the destination - * is at the top-left corner. + * This function copies parts of a framebuffer to display memory. Destination and + * framebuffer formats must match. No conversion takes place. The parameters @dst, + * @dst_pitch and @vmap refer to arrays. Each array must have at least as many entries + * as there are planes in @fb's format. Each entry stores the value for the format's + * respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). */ -void drm_fb_memcpy(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - unsigned int cpp = fb->format->cpp[0]; - size_t len = (clip->x2 - clip->x1) * cpp; - unsigned int y, lines = clip->y2 - clip->y1; + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + const struct drm_format_info *format = fb->format; + unsigned int i, y, lines = drm_rect_height(clip); if (!dst_pitch) - dst_pitch = len; + dst_pitch = default_dst_pitch; - vaddr += clip_offset(clip, fb->pitches[0], cpp); - for (y = 0; y < lines; y++) { - memcpy(dst, vaddr, len); - vaddr += fb->pitches[0]; - dst += dst_pitch; + for (i = 0; i < format->num_planes; ++i) { + unsigned int bpp_i = drm_format_info_bpp(format, i); + unsigned int cpp_i = DIV_ROUND_UP(bpp_i, 8); + size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8); + unsigned int dst_pitch_i = dst_pitch[i]; + struct iosys_map dst_i = dst[i]; + struct iosys_map vmap_i = vmap[i]; + + if (!dst_pitch_i) + dst_pitch_i = len_i; + + iosys_map_incr(&vmap_i, clip_offset(clip, fb->pitches[i], cpp_i)); + for (y = 0; y < lines; y++) { + /* TODO: handle vmap_i in I/O memory here */ + iosys_map_memcpy_to(&dst_i, 0, vmap_i.vaddr, len_i); + iosys_map_incr(&vmap_i, fb->pitches[i]); + iosys_map_incr(&dst_i, dst_pitch_i); + } } } EXPORT_SYMBOL(drm_fb_memcpy); -/** - * drm_fb_memcpy_toio - Copy clip buffer - * @dst: Destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: Source buffer - * @fb: DRM framebuffer - * @clip: Clip rectangle area to copy - * - * This function does not apply clipping on dst, i.e. the destination - * is at the top-left corner. - */ -void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) -{ - unsigned int cpp = fb->format->cpp[0]; - size_t len = (clip->x2 - clip->x1) * cpp; - unsigned int y, lines = clip->y2 - clip->y1; - - if (!dst_pitch) - dst_pitch = len; - - vaddr += clip_offset(clip, fb->pitches[0], cpp); - for (y = 0; y < lines; y++) { - memcpy_toio(dst, vaddr, len); - vaddr += fb->pitches[0]; - dst += dst_pitch; - } -} -EXPORT_SYMBOL(drm_fb_memcpy_toio); - static void drm_fb_swab16_line(void *dbuf, const void *sbuf, unsigned int pixels) { u16 *dbuf16 = dbuf; @@ -587,7 +581,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d dst_format = DRM_FORMAT_XRGB2101010; if (dst_format == fb_format) { - drm_fb_memcpy_toio(dst[0].vaddr_iomem, dst_pitch[0], vmap[0].vaddr, fb, clip); + drm_fb_memcpy(dst, dst_pitch, vmap, fb, clip); return 0; } else if (dst_format == DRM_FORMAT_RGB565) { diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 2ecaf3cb7afb..1ba506ca83e1 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -205,6 +205,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); struct iosys_map map[DRM_FORMAT_MAX_PLANES]; struct iosys_map data[DRM_FORMAT_MAX_PLANES]; + struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst); void *src; int ret; @@ -222,7 +223,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, if (swap) drm_fb_swab(dst, 0, src, fb, clip, !gem->import_attach); else - drm_fb_memcpy(dst, 0, src, fb, clip); + drm_fb_memcpy(&dst_map, NULL, data, fb, clip); break; case DRM_FORMAT_XRGB8888: drm_fb_xrgb8888_to_rgb565(dst, 0, src, fb, clip, swap); diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index d42592f6daab..449c95a4aee0 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -156,6 +156,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, u8 compression = gdrm->compression; struct iosys_map map[DRM_FORMAT_MAX_PLANES]; struct iosys_map map_data[DRM_FORMAT_MAX_PLANES]; + struct iosys_map dst; void *vaddr, *buf; size_t pitch, len; int ret = 0; @@ -179,6 +180,7 @@ retry: buf = gdrm->compress_buf; else buf = gdrm->bulk_buf; + iosys_map_set_vaddr(&dst, buf); /* * Imported buffers are assumed to be write-combined and thus uncached @@ -208,7 +210,7 @@ retry: /* can compress directly from the framebuffer */ buf = vaddr + rect->y1 * pitch; } else { - drm_fb_memcpy(buf, 0, vaddr, fb, rect); + drm_fb_memcpy(&dst, NULL, map_data, fb, rect); } memset(req, 0, sizeof(*req)); diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c index b8e64dd8d3a6..28e732f94bf2 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c @@ -21,19 +21,18 @@ #include "hyperv_drm.h" static int hyperv_blit_to_vram_rect(struct drm_framebuffer *fb, - const struct iosys_map *map, + const struct iosys_map *vmap, struct drm_rect *rect) { struct hyperv_drm_device *hv = to_hv(fb->dev); - void __iomem *dst = hv->vram; - void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ + struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(hv->vram); int idx; if (!drm_dev_enter(&hv->dev, &idx)) return -ENODEV; - dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect); - drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect); + iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, rect)); + drm_fb_memcpy(&dst, fb->pitches, vmap, fb, rect); drm_dev_exit(idx); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 1f26d4716679..bbab2549243a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -430,13 +430,12 @@ static void mgag200_disable_display(struct mga_device *mdev) } static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_map *vmap, - struct drm_framebuffer *fb, const struct drm_rect *clip) + struct drm_framebuffer *fb, struct drm_rect *clip) { - void __iomem *dst = mdev->vram; - void *vaddr = vmap[0].vaddr; /* TODO: Use mapping abstraction properly */ + struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram); - dst += drm_fb_clip_offset(fb->pitches[0], fb->format, clip); - drm_fb_memcpy_toio(dst, fb->pitches[0], vaddr, fb, clip); + iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip)); + drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip); } /* diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index c4f5beea1f90..73fb9f63d227 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -316,28 +316,31 @@ static int cirrus_mode_set(struct cirrus_device *cirrus, } static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, - const struct iosys_map *map, + const struct iosys_map *vmap, struct drm_rect *rect) { struct cirrus_device *cirrus = to_cirrus(fb->dev); - void __iomem *dst = cirrus->vram; - void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ + struct iosys_map dst; + void *vaddr = vmap->vaddr; /* TODO: Use mapping abstraction properly */ int idx; if (!drm_dev_enter(&cirrus->dev, &idx)) return -ENODEV; + iosys_map_set_vaddr_iomem(&dst, cirrus->vram); + if (cirrus->cpp == fb->format->cpp[0]) { - dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect); - drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect); + iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, rect)); + drm_fb_memcpy(&dst, fb->pitches, vmap, fb, rect); } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) { - dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect); - drm_fb_xrgb8888_to_rgb565_toio(dst, cirrus->pitch, vmap, fb, rect, false); + iosys_map_incr(&dst, drm_fb_clip_offset(cirrus->pitch, fb->format, rect)); + drm_fb_xrgb8888_to_rgb565_toio(dst.vaddr_iomem, cirrus->pitch, vaddr, fb, rect, + false); } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) { - dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect); - drm_fb_xrgb8888_to_rgb888_toio(dst, cirrus->pitch, vmap, fb, rect); + iosys_map_incr(&dst, drm_fb_clip_offset(cirrus->pitch, fb->format, rect)); + drm_fb_xrgb8888_to_rgb888_toio(dst.vaddr_iomem, cirrus->pitch, vaddr, fb, rect); } else { WARN_ON_ONCE("cpp mismatch"); diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 21daea7fda99..8af6a2717bc9 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -14,10 +14,9 @@ struct drm_rect; unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format, const struct drm_rect *clip); -void drm_fb_memcpy(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip); -void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool cached); From ce582859ca7b33e5c0d9432da9f7b54ced802100 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:53:56 +0200 Subject: [PATCH 259/396] drm/format-helper: Convert drm_fb_swab() to struct iosys_map Convert drm_fb_swab() to use struct iosys_map() and convert users. The new interface supports multi-plane color formats, but implementation only supports a single plane for now. v2: * use drm_format_info_bpp() (Sam) * update documentation (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-5-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 53 +++++++++++++++++++++-------- drivers/gpu/drm/drm_mipi_dbi.c | 2 +- drivers/gpu/drm/gud/gud_pipe.c | 2 +- include/drm/drm_format_helper.h | 6 ++-- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 7489c665a47c..b5ed058984ae 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -205,37 +205,62 @@ static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels /** * drm_fb_swab - Swap bytes into clip buffer - * @dst: Destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @src: Source buffer + * @dst: Array of destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @cached: Source buffer is mapped cached (eg. not write-combined) * - * If @cached is false a temporary buffer is used to cache one pixel line at a - * time to speed up slow uncached reads. + * This function copies parts of a framebuffer to display memory and swaps per-pixel + * bytes during the process. Destination and framebuffer formats must match. The + * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * least as many entries as there are planes in @fb's format. Each entry stores the + * value for the format's respective color plane at the same index. If @cached is + * false a temporary buffer is used to cache one pixel line at a time to speed up + * slow uncached reads. * - * This function does not apply clipping on dst, i.e. the destination - * is at the top-left corner. + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). */ -void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip, - bool cached) +void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool cached) { - u8 cpp = fb->format->cpp[0]; + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + const struct drm_format_info *format = fb->format; + u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8); + void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels); switch (cpp) { case 4: - drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab32_line); + swab_line = drm_fb_swab32_line; break; case 2: - drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab16_line); + swab_line = drm_fb_swab16_line; break; default: drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n", - &fb->format->format); + &format->format); + swab_line = NULL; break; } + if (!swab_line) + return; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst->is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], cpp, + vmap[0].vaddr, fb, clip, cached, swab_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], cpp, vmap[0].vaddr, fb, + clip, cached, swab_line); } EXPORT_SYMBOL(drm_fb_swab); diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 1ba506ca83e1..a44b7d6ae06c 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -221,7 +221,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, switch (fb->format->format) { case DRM_FORMAT_RGB565: if (swap) - drm_fb_swab(dst, 0, src, fb, clip, !gem->import_attach); + drm_fb_swab(&dst_map, NULL, data, fb, clip, !gem->import_attach); else drm_fb_memcpy(&dst_map, NULL, data, fb, clip); break; diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 449c95a4aee0..a15cda9ba058 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -205,7 +205,7 @@ retry: len = gud_xrgb8888_to_color(buf, format, vaddr, fb, rect); } } else if (gud_is_big_endian() && format->cpp[0] > 1) { - drm_fb_swab(buf, 0, vaddr, fb, rect, !import_attach); + drm_fb_swab(&dst, NULL, map_data, fb, rect, !import_attach); } else if (compression && !import_attach && pitch == fb->pitches[0]) { /* can compress directly from the framebuffer */ buf = vaddr + rect->y1 * pitch; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 8af6a2717bc9..60944feaa936 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -17,9 +17,9 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip); -void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip, - bool cached); +void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool cached); void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *vaddr, const struct drm_framebuffer *fb, const struct drm_rect *clip); void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr, From e13140a06283141318319aaae7dfa348b06bdd6c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:53:57 +0200 Subject: [PATCH 260/396] drm/format-helper: Rework XRGB8888-to-RGBG332 conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update XRGB8888-to-RGB332 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * rebase onto refactored Kunit tests * update documentation (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-6-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 38 +++++++++++++++---- drivers/gpu/drm/gud/gud_pipe.c | 2 +- .../gpu/drm/tests/drm_format_helper_test.c | 20 +++++----- include/drm/drm_format_helper.h | 5 ++- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index b5ed058984ae..248fd87f0a36 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -281,18 +281,42 @@ static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigne /** * drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer - * @dst: RGB332 destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @src: XRGB8888 source buffer + * @dst: Array of RGB332 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * - * Drivers can use this function for RGB332 devices that don't natively support XRGB8888. + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. Destination and framebuffer formats must match. The + * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * least as many entries as there are planes in @fb's format. Each entry stores the + * value for the format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for RGB332 devices that don't support XRGB8888 natively. */ -void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm(dst, dst_pitch, 1, src, fb, clip, false, drm_fb_xrgb8888_to_rgb332_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, vmap[0].vaddr, fb, clip, + false, drm_fb_xrgb8888_to_rgb332_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb, clip, + false, drm_fb_xrgb8888_to_rgb332_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index a15cda9ba058..426a3ae6cc50 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -196,7 +196,7 @@ retry: } else if (format->format == DRM_FORMAT_R8) { drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, rect); } else if (format->format == DRM_FORMAT_RGB332) { - drm_fb_xrgb8888_to_rgb332(buf, 0, vaddr, fb, rect); + drm_fb_xrgb8888_to_rgb332(&dst, NULL, map_data, fb, rect); } else if (format->format == DRM_FORMAT_RGB565) { drm_fb_xrgb8888_to_rgb565(buf, 0, vaddr, fb, rect, gud_is_big_endian()); } else if (format->format == DRM_FORMAT_RGB888) { diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 26ecf3b4b137..7b14694ead59 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -197,8 +197,9 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) const struct convert_xrgb8888_case *params = test->param_value; const struct convert_to_rgb332_result *result = ¶ms->rgb332_result; size_t dst_size; - __u8 *dst = NULL; - __u32 *src = NULL; + __u8 *buf = NULL; + __u32 *xrgb8888 = NULL; + struct iosys_map dst, src; struct drm_framebuffer fb = { .format = drm_format_info(DRM_FORMAT_XRGB8888), @@ -209,15 +210,16 @@ static void xrgb8888_to_rgb332_test(struct kunit *test) ¶ms->clip); KUNIT_ASSERT_GT(test, dst_size, 0); - dst = kunit_kzalloc(test, dst_size, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dst); + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + iosys_map_set_vaddr(&dst, buf); - src = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, src); + xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888); + iosys_map_set_vaddr(&src, xrgb8888); - drm_fb_xrgb8888_to_rgb332(dst, result->dst_pitch, src, &fb, - ¶ms->clip); - KUNIT_EXPECT_EQ(test, memcmp(dst, result->expected, dst_size), 0); + drm_fb_xrgb8888_to_rgb332(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); } static void xrgb8888_to_rgb565_test(struct kunit *test) diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 60944feaa936..3c28f099e3ed 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -20,8 +20,9 @@ void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool cached); -void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool swab); From ab298c29d414a5a94ed3039b0e97bc325bf45272 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:53:58 +0200 Subject: [PATCH 261/396] drm/format-helper: Rework XRGB8888-to-RGBG565 conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update XRGB8888-to-RGB565 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * update new Kunit tests * update documentation (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-7-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 75 +++++++++---------- drivers/gpu/drm/drm_mipi_dbi.c | 4 +- drivers/gpu/drm/gud/gud_pipe.c | 3 +- .../gpu/drm/tests/drm_format_helper_test.c | 25 ++++--- drivers/gpu/drm/tiny/cirrus.c | 3 +- include/drm/drm_format_helper.h | 9 +-- 6 files changed, 56 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 248fd87f0a36..a77291d2f9b9 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -357,54 +357,52 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, /** * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer - * @dst: RGB565 destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB8888 source buffer + * @dst: Array of RGB565 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @swab: Swap bytes * - * Drivers can use this function for RGB565 devices that don't natively - * support XRGB8888. + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. Destination and framebuffer formats must match. The + * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * least as many entries as there are planes in @fb's format. Each entry stores the + * value for the format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for RGB565 devices that don't support XRGB8888 natively. */ -void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip, - bool swab) +void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool swab) { + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels); + if (swab) - drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false, - drm_fb_xrgb8888_to_rgb565_swab_line); + xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line; else - drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false, - drm_fb_xrgb8888_to_rgb565_line); + xfrm_line = drm_fb_xrgb8888_to_rgb565_line; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 2, vmap[0].vaddr, fb, clip, + false, xfrm_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 2, vmap[0].vaddr, fb, clip, + false, xfrm_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); -/** - * drm_fb_xrgb8888_to_rgb565_toio - Convert XRGB8888 to RGB565 clip buffer - * @dst: RGB565 destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB8888 source buffer - * @fb: DRM framebuffer - * @clip: Clip rectangle area to copy - * @swab: Swap bytes - * - * Drivers can use this function for RGB565 devices that don't natively - * support XRGB8888. - */ -void drm_fb_xrgb8888_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip, bool swab) -{ - if (swab) - drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false, - drm_fb_xrgb8888_to_rgb565_swab_line); - else - drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false, - drm_fb_xrgb8888_to_rgb565_line); -} -EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_toio); - static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels) { u8 *dbuf8 = dbuf; @@ -635,8 +633,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } else if (dst_format == DRM_FORMAT_RGB565) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb565_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip, false); + drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, vmap, fb, clip, false); return 0; } } else if (dst_format == DRM_FORMAT_RGB888) { diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index a44b7d6ae06c..84abc3920b57 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -206,7 +206,6 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, struct iosys_map map[DRM_FORMAT_MAX_PLANES]; struct iosys_map data[DRM_FORMAT_MAX_PLANES]; struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst); - void *src; int ret; ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); @@ -216,7 +215,6 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, ret = drm_gem_fb_vmap(fb, map, data); if (ret) goto out_drm_gem_fb_end_cpu_access; - src = data[0].vaddr; /* TODO: Use mapping abstraction properly */ switch (fb->format->format) { case DRM_FORMAT_RGB565: @@ -226,7 +224,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, drm_fb_memcpy(&dst_map, NULL, data, fb, clip); break; case DRM_FORMAT_XRGB8888: - drm_fb_xrgb8888_to_rgb565(dst, 0, src, fb, clip, swap); + drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, data, fb, clip, swap); break; default: drm_err_once(fb->dev, "Format is not supported: %p4cc\n", diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 426a3ae6cc50..a43eb6645352 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -198,7 +198,8 @@ retry: } else if (format->format == DRM_FORMAT_RGB332) { drm_fb_xrgb8888_to_rgb332(&dst, NULL, map_data, fb, rect); } else if (format->format == DRM_FORMAT_RGB565) { - drm_fb_xrgb8888_to_rgb565(buf, 0, vaddr, fb, rect, gud_is_big_endian()); + drm_fb_xrgb8888_to_rgb565(&dst, NULL, map_data, fb, rect, + gud_is_big_endian()); } else if (format->format == DRM_FORMAT_RGB888) { drm_fb_xrgb8888_to_rgb888(buf, 0, vaddr, fb, rect); } else { diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 7b14694ead59..828487071796 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -227,8 +227,9 @@ static void xrgb8888_to_rgb565_test(struct kunit *test) const struct convert_xrgb8888_case *params = test->param_value; const struct convert_to_rgb565_result *result = ¶ms->rgb565_result; size_t dst_size; - __u16 *dst = NULL; - __u32 *src = NULL; + __u16 *buf = NULL; + __u32 *xrgb8888 = NULL; + struct iosys_map dst, src; struct drm_framebuffer fb = { .format = drm_format_info(DRM_FORMAT_XRGB8888), @@ -239,19 +240,19 @@ static void xrgb8888_to_rgb565_test(struct kunit *test) ¶ms->clip); KUNIT_ASSERT_GT(test, dst_size, 0); - dst = kunit_kzalloc(test, dst_size, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dst); + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + iosys_map_set_vaddr(&dst, buf); - src = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, src); + xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888); + iosys_map_set_vaddr(&src, xrgb8888); - drm_fb_xrgb8888_to_rgb565(dst, result->dst_pitch, src, &fb, - ¶ms->clip, false); - KUNIT_EXPECT_EQ(test, memcmp(dst, result->expected, dst_size), 0); + drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, false); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); - drm_fb_xrgb8888_to_rgb565(dst, result->dst_pitch, src, &fb, - ¶ms->clip, true); - KUNIT_EXPECT_EQ(test, memcmp(dst, result->expected_swab, dst_size), 0); + drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, true); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected_swab, dst_size), 0); } static struct kunit_case drm_format_helper_test_cases[] = { diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 73fb9f63d227..9cd398e4700b 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -335,8 +335,7 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) { iosys_map_incr(&dst, drm_fb_clip_offset(cirrus->pitch, fb->format, rect)); - drm_fb_xrgb8888_to_rgb565_toio(dst.vaddr_iomem, cirrus->pitch, vaddr, fb, rect, - false); + drm_fb_xrgb8888_to_rgb565(&dst, &cirrus->pitch, vmap, fb, rect, false); } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) { iosys_map_incr(&dst, drm_fb_clip_offset(cirrus->pitch, fb->format, rect)); diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 3c28f099e3ed..9f1d45d7ce84 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -23,12 +23,9 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip); -void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip, - bool swab); -void drm_fb_xrgb8888_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip, bool swab); +void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool swab); void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch, From c4863ce0f4aa17d88f4bf5fbd92ae9400f6e6d28 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:53:59 +0200 Subject: [PATCH 262/396] drm/format-helper: Rework XRGB8888-to-RGB888 conversion Update XRGB8888-to-RGB888 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * update documentation (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-8-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 59 +++++++++++++++-------------- drivers/gpu/drm/gud/gud_pipe.c | 2 +- drivers/gpu/drm/tiny/cirrus.c | 3 +- include/drm/drm_format_helper.h | 8 ++-- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index a77291d2f9b9..3ee57dc8bcc5 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -420,42 +420,46 @@ static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigne /** * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer - * @dst: RGB888 destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @src: XRGB8888 source buffer + * @dst: Array of RGB888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. Destination and framebuffer formats must match. The + * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * least as many entries as there are planes in @fb's format. Each entry stores the + * value for the format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * * Drivers can use this function for RGB888 devices that don't natively * support XRGB8888. */ -void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm(dst, dst_pitch, 3, src, fb, clip, false, drm_fb_xrgb8888_to_rgb888_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 3, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb8888_to_rgb888_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 3, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb8888_to_rgb888_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); -/** - * drm_fb_xrgb8888_to_rgb888_toio - Convert XRGB8888 to RGB888 clip buffer - * @dst: RGB565 destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB8888 source buffer - * @fb: DRM framebuffer - * @clip: Clip rectangle area to copy - * - * Drivers can use this function for RGB888 devices that don't natively - * support XRGB8888. - */ -void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip) -{ - drm_fb_xfrm_toio(dst, dst_pitch, 3, vaddr, fb, clip, false, - drm_fb_xrgb8888_to_rgb888_line); -} -EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio); - static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { __le32 *dbuf32 = dbuf; @@ -638,8 +642,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } } else if (dst_format == DRM_FORMAT_RGB888) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb888_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, vmap, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB8888) { diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index a43eb6645352..0caa228f736d 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -201,7 +201,7 @@ retry: drm_fb_xrgb8888_to_rgb565(&dst, NULL, map_data, fb, rect, gud_is_big_endian()); } else if (format->format == DRM_FORMAT_RGB888) { - drm_fb_xrgb8888_to_rgb888(buf, 0, vaddr, fb, rect); + drm_fb_xrgb8888_to_rgb888(&dst, NULL, map_data, fb, rect); } else { len = gud_xrgb8888_to_color(buf, format, vaddr, fb, rect); } diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 9cd398e4700b..354d5e854a6f 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -321,7 +321,6 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, { struct cirrus_device *cirrus = to_cirrus(fb->dev); struct iosys_map dst; - void *vaddr = vmap->vaddr; /* TODO: Use mapping abstraction properly */ int idx; if (!drm_dev_enter(&cirrus->dev, &idx)) @@ -339,7 +338,7 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) { iosys_map_incr(&dst, drm_fb_clip_offset(cirrus->pitch, fb->format, rect)); - drm_fb_xrgb8888_to_rgb888_toio(dst.vaddr_iomem, cirrus->pitch, vaddr, fb, rect); + drm_fb_xrgb8888_to_rgb888(&dst, &cirrus->pitch, vmap, fb, rect); } else { WARN_ON_ONCE("cpp mismatch"); diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 9f1d45d7ce84..8c633dbab5d6 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -26,11 +26,9 @@ void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool swab); -void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip); -void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip); +void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst, unsigned int dst_pitch, const void *vaddr, const struct drm_framebuffer *fb, const struct drm_rect *clip); From cb7fffbd26dd6eadfe6591c0e14fb43e1ba2f70e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:54:00 +0200 Subject: [PATCH 263/396] drm/format-helper: Rework RGB565-to-XRGB8888 conversion Update RGB565-to-XRGB8888 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-9-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 3ee57dc8bcc5..b390d529afeb 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -478,12 +478,25 @@ static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne } } -static void drm_fb_rgb565_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip) +static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, + const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false, - drm_fb_rgb565_to_xrgb8888_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_rgb565_to_xrgb8888_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_rgb565_to_xrgb8888_line); } static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) @@ -651,8 +664,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d vmap[0].vaddr, fb, clip); return 0; } else if (fb_format == DRM_FORMAT_RGB565) { - drm_fb_rgb565_to_xrgb8888_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, vmap, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB2101010) { From cfe637c4d6fcaffa655405e682f99a3d88e5fad0 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:54:01 +0200 Subject: [PATCH 264/396] drm/format-helper: Rework RGB888-to-XRGB8888 conversion Update RGB888-to-XRGB8888 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-10-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index b390d529afeb..8083f5b85b3a 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -514,12 +514,25 @@ static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne } } -static void drm_fb_rgb888_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip) +static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, + const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false, - drm_fb_rgb888_to_xrgb8888_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_rgb888_to_xrgb8888_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_rgb888_to_xrgb8888_line); } static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) @@ -660,8 +673,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } } else if (dst_format == DRM_FORMAT_XRGB8888) { if (fb_format == DRM_FORMAT_RGB888) { - drm_fb_rgb888_to_xrgb8888_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, vmap, fb, clip); return 0; } else if (fb_format == DRM_FORMAT_RGB565) { drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, vmap, fb, clip); From ce73f456744ca763ab6a9753104caf843d30fd8b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:54:02 +0200 Subject: [PATCH 265/396] drm/format-helper: Rework XRGB8888-to-XRGB2101010 conversion Update XRGB8888-to-XRGB2101010 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * update documentation (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-11-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 50 ++++++++++++++++++++--------- include/drm/drm_format_helper.h | 6 ++-- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 8083f5b85b3a..795d845c7e53 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -554,26 +554,45 @@ static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, un } /** - * drm_fb_xrgb8888_to_xrgb2101010_toio - Convert XRGB8888 to XRGB2101010 clip - * buffer - * @dst: XRGB2101010 destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB8888 source buffer + * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer + * @dst: Array of XRGB2101010 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * - * Drivers can use this function for XRGB2101010 devices that don't natively - * support XRGB8888. + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. Destination and framebuffer formats must match. The + * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * least as many entries as there are planes in @fb's format. Each entry stores the + * value for the format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888 + * natively. */ -void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst, - unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, - const struct drm_rect *clip) +void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false, - drm_fb_xrgb8888_to_xrgb2101010_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb8888_to_xrgb2101010_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb8888_to_xrgb2101010_line); } -EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio); static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) { @@ -681,8 +700,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } } else if (dst_format == DRM_FORMAT_XRGB2101010) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_xrgb2101010_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, vmap, fb, clip); return 0; } } diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 8c633dbab5d6..6807440ce29c 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -29,9 +29,9 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip); -void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip); +void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, const struct drm_framebuffer *fb, const struct drm_rect *clip); From 7bef64490f9bb04731d3cf46bc8f7f46e55b2e0e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:54:03 +0200 Subject: [PATCH 266/396] drm/format-helper: Rework XRGB8888-to-GRAY8 conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update XRGB8888-to-GRAY8 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * update documentation (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-12-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 46 +++++++++++++++++++++-------- drivers/gpu/drm/gud/gud_pipe.c | 7 +++-- drivers/gpu/drm/tiny/st7586.c | 5 +++- include/drm/drm_format_helper.h | 5 ++-- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 795d845c7e53..890370c0424f 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -613,25 +613,47 @@ static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned /** * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale - * @dst: 8-bit grayscale destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB8888 source buffer + * @dst: Array of 8-bit grayscale destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * - * Drm doesn't have native monochrome or grayscale support. - * Such drivers can announce the commonly supported XR24 format to userspace - * and use this function to convert to the native format. + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. Destination and framebuffer formats must match. The + * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * least as many entries as there are planes in @fb's format. Each entry stores the + * value for the format's respective color plane at the same index. * - * Monochrome drivers will use the most significant bit, - * where 1 means foreground color and 0 background color. + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). * - * ITU BT.601 is used for the RGB -> luma (brightness) conversion. + * DRM doesn't have native monochrome or grayscale support. Drivers can use this + * function for grayscale devices that don't support XRGB8888 natively.Such + * drivers can announce the commonly supported XR24 format to userspace and use + * this function to convert to the native format. Monochrome drivers will use the + * most significant bit, where 1 means foreground color and 0 background color. + * ITU BT.601 is being used for the RGB -> luma (brightness) conversion. */ -void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm(dst, dst_pitch, 1, vaddr, fb, clip, false, drm_fb_xrgb8888_to_gray8_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb8888_to_gray8_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb8888_to_gray8_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 0caa228f736d..7c6dc2bcd14a 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -59,6 +59,7 @@ static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format unsigned int bits_per_pixel = 8 / block_width; unsigned int x, y, width, height; u8 pix, *pix8, *block = dst; /* Assign to silence compiler warning */ + struct iosys_map dst_map, vmap; size_t len; void *buf; @@ -74,7 +75,9 @@ static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format if (!buf) return 0; - drm_fb_xrgb8888_to_gray8(buf, 0, src, fb, rect); + iosys_map_set_vaddr(&dst_map, buf); + iosys_map_set_vaddr(&vmap, src); + drm_fb_xrgb8888_to_gray8(&dst_map, NULL, &vmap, fb, rect); pix8 = buf; for (y = 0; y < height; y++) { @@ -194,7 +197,7 @@ retry: goto end_cpu_access; } } else if (format->format == DRM_FORMAT_R8) { - drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, rect); + drm_fb_xrgb8888_to_gray8(&dst, NULL, map_data, fb, rect); } else if (format->format == DRM_FORMAT_RGB332) { drm_fb_xrgb8888_to_rgb332(&dst, NULL, map_data, fb, rect); } else if (format->format == DRM_FORMAT_RGB565) { diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 94f55fac4295..b6f620b902e6 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -69,12 +69,15 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, size_t len = (clip->x2 - clip->x1) * (clip->y2 - clip->y1); unsigned int x, y; u8 *src, *buf, val; + struct iosys_map dst_map, vmap; buf = kmalloc(len, GFP_KERNEL); if (!buf) return; - drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, clip); + iosys_map_set_vaddr(&dst_map, buf); + iosys_map_set_vaddr(&vmap, vaddr); + drm_fb_xrgb8888_to_gray8(&dst_map, NULL, &vmap, fb, clip); src = buf; for (y = clip->y1; y < clip->y2; y++) { diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 6807440ce29c..68087c982497 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -32,8 +32,9 @@ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip); -void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip); int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, const struct iosys_map *vmap, const struct drm_framebuffer *fb, From b3aca563d69bcbb49343196b4265a8cb7db91bfa Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:54:04 +0200 Subject: [PATCH 267/396] drm/format-helper: Rework XRGB8888-to-MONO conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update XRGB8888-to-MONO conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). v2: * rebase after renaming CMA helpers to DMA helpers * update documentation (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-13-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 56 +++++++++++++++++++---------- drivers/gpu/drm/solomon/ssd130x.c | 7 ++-- drivers/gpu/drm/tiny/repaper.c | 6 +++- include/drm/drm_format_helper.h | 5 +-- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 890370c0424f..53a313f83dc2 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -753,46 +753,64 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int /** * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome - * @dst: monochrome destination buffer (0=black, 1=white) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB8888 source buffer + * @dst: Array of monochrome destination buffers (0=black, 1=white) + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @vmap: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * - * DRM doesn't have native monochrome support. - * Such drivers can announce the commonly supported XR24 format to userspace - * and use this function to convert to the native format. + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. Destination and framebuffer formats must match. The + * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * least as many entries as there are planes in @fb's format. Each entry stores the + * value for the format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). The first pixel (upper left corner of the clip rectangle) will + * be converted and copied to the first bit (LSB) in the first byte of the monochrome + * destination buffer. If the caller requires that the first pixel in a byte must + * be located at an x-coordinate that is a multiple of 8, then the caller must take + * care itself of supplying a suitable clip rectangle. + * + * DRM doesn't have native monochrome support. Drivers can use this function for + * monochrome devices that don't support XRGB8888 natively. Such drivers can + * announce the commonly supported XR24 format to userspace and use this function + * to convert to the native format. * * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and * then the result is converted from grayscale to monochrome. - * - * The first pixel (upper left corner of the clip rectangle) will be converted - * and copied to the first bit (LSB) in the first byte of the monochrome - * destination buffer. - * If the caller requires that the first pixel in a byte must be located at an - * x-coordinate that is a multiple of 8, then the caller must take care itself - * of supplying a suitable clip rectangle. */ -void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; unsigned int linepixels = drm_rect_width(clip); unsigned int lines = drm_rect_height(clip); unsigned int cpp = fb->format->cpp[0]; unsigned int len_src32 = linepixels * cpp; struct drm_device *dev = fb->dev; + void *vaddr = vmap[0].vaddr; + unsigned int dst_pitch_0; unsigned int y; - u8 *mono = dst, *gray8; + u8 *mono = dst[0].vaddr, *gray8; u32 *src32; if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888)) return; + if (!dst_pitch) + dst_pitch = default_dst_pitch; + dst_pitch_0 = dst_pitch[0]; + /* * The mono destination buffer contains 1 bit per pixel */ - if (!dst_pitch) - dst_pitch = DIV_ROUND_UP(linepixels, 8); + if (!dst_pitch_0) + dst_pitch_0 = DIV_ROUND_UP(linepixels, 8); /* * The dma memory is write-combined so reads are uncached. @@ -817,7 +835,7 @@ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vadd drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels); drm_fb_gray8_to_mono_line(mono, gray8, linepixels); vaddr += fb->pitches[0]; - mono += dst_pitch; + mono += dst_pitch_0; } kfree(src32); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 973ae2dfb2f8..f87f5443e714 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -536,11 +536,11 @@ static void ssd130x_clear_screen(struct ssd130x_device *ssd130x) kfree(buf); } -static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *map, +static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *vmap, struct drm_rect *rect) { struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev); - void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ + struct iosys_map dst; unsigned int dst_pitch; int ret = 0; u8 *buf = NULL; @@ -554,7 +554,8 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_m if (!buf) return -ENOMEM; - drm_fb_xrgb8888_to_mono(buf, dst_pitch, vmap, fb, rect); + iosys_map_set_vaddr(&dst, buf); + drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect); ssd130x_update_rect(ssd130x, buf, rect); diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 4cd24b54ac74..c4c1be3ac0b8 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -513,6 +513,8 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) { struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct repaper_epd *epd = drm_to_epd(fb->dev); + unsigned int dst_pitch = 0; + struct iosys_map dst, vmap; struct drm_rect clip; int idx, ret = 0; u8 *buf = NULL; @@ -541,7 +543,9 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) if (ret) goto out_free; - drm_fb_xrgb8888_to_mono(buf, 0, dma_obj->vaddr, fb, &clip); + iosys_map_set_vaddr(&dst, buf); + iosys_map_set_vaddr(&vmap, dma_obj->vaddr); + drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, &vmap, fb, &clip); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 68087c982497..1e1d8f356cc1 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -40,7 +40,8 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *rect); -void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip); #endif /* __LINUX_DRM_FORMAT_HELPER_H */ From f241b064426943a1591c9e9121a175d5ed1edb42 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:54:05 +0200 Subject: [PATCH 268/396] drm/format-helper: Move destination-buffer handling into internal helper The format-convertion helpers handle several cases for different values of destination buffer and pitch. Move that code into the internal helper drm_fb_xfrm() and avoid quite a bit of duplication. v2: * remove a duplicated blank line (Jose) * use drm_format_info_bpp() (Sam) * fix vaddr_cached_hint bug (Sam) * add TODO on vaddr location (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-14-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 174 ++++++++++------------------ 1 file changed, 63 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 53a313f83dc2..0fec3b68db95 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -41,11 +41,11 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info } EXPORT_SYMBOL(drm_fb_clip_offset); -/* TODO: Make this functon work with multi-plane formats. */ -static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip, bool vaddr_cached_hint, - void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) +/* TODO: Make this function work with multi-plane formats. */ +static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool vaddr_cached_hint, + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) { unsigned long linepixels = drm_rect_width(clip); unsigned long lines = drm_rect_height(clip); @@ -84,11 +84,11 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix return 0; } -/* TODO: Make this functon work with multi-plane formats. */ -static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip, bool vaddr_cached_hint, - void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) +/* TODO: Make this function work with multi-plane formats. */ +static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool vaddr_cached_hint, + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) { unsigned long linepixels = drm_rect_width(clip); unsigned long lines = drm_rect_height(clip); @@ -129,6 +129,29 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned return 0; } +/* TODO: Make this function work with multi-plane formats. */ +static int drm_fb_xfrm(struct iosys_map *dst, + const unsigned int *dst_pitch, const u8 *dst_pixsize, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool vaddr_cached_hint, + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) +{ + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + /* TODO: handle vmap in I/O memory here */ + if (dst[0].is_iomem) + return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0], + vmap[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); + else + return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0], + vmap[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); +} + /** * drm_fb_memcpy - Copy clip buffer * @dst: Array of destination buffers @@ -228,9 +251,6 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool cached) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 - }; const struct drm_format_info *format = fb->format; u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8); void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels); @@ -245,22 +265,10 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, default: drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n", &format->format); - swab_line = NULL; - break; - } - if (!swab_line) return; + } - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst->is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], cpp, - vmap[0].vaddr, fb, clip, cached, swab_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], cpp, vmap[0].vaddr, fb, - clip, cached, swab_line); + drm_fb_xfrm(dst, dst_pitch, &cpp, vmap, fb, clip, cached, swab_line); } EXPORT_SYMBOL(drm_fb_swab); @@ -303,20 +311,12 @@ void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pi const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 1, }; - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst[0].is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, vmap[0].vaddr, fb, clip, - false, drm_fb_xrgb8888_to_rgb332_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb, clip, - false, drm_fb_xrgb8888_to_rgb332_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xrgb8888_to_rgb332_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); @@ -380,9 +380,10 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool swab) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 2, }; + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels); if (swab) @@ -390,16 +391,7 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi else xfrm_line = drm_fb_xrgb8888_to_rgb565_line; - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst[0].is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 2, vmap[0].vaddr, fb, clip, - false, xfrm_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 2, vmap[0].vaddr, fb, clip, - false, xfrm_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, xfrm_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); @@ -443,20 +435,12 @@ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pi const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 3, }; - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst[0].is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 3, vmap[0].vaddr, fb, - clip, false, drm_fb_xrgb8888_to_rgb888_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 3, vmap[0].vaddr, fb, - clip, false, drm_fb_xrgb8888_to_rgb888_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xrgb8888_to_rgb888_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); @@ -483,20 +467,12 @@ static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int const struct drm_framebuffer *fb, const struct drm_rect *clip) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, }; - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst[0].is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, - clip, false, drm_fb_rgb565_to_xrgb8888_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, - clip, false, drm_fb_rgb565_to_xrgb8888_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_rgb565_to_xrgb8888_line); } static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) @@ -519,20 +495,12 @@ static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int const struct drm_framebuffer *fb, const struct drm_rect *clip) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, }; - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst[0].is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, - clip, false, drm_fb_rgb888_to_xrgb8888_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, - clip, false, drm_fb_rgb888_to_xrgb8888_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_rgb888_to_xrgb8888_line); } static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) @@ -578,20 +546,12 @@ void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *d const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, }; - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst[0].is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, - clip, false, drm_fb_xrgb8888_to_xrgb2101010_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, - clip, false, drm_fb_xrgb8888_to_xrgb2101010_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xrgb8888_to_xrgb2101010_line); } static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) @@ -640,20 +600,12 @@ void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pit const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 1, }; - if (!dst_pitch) - dst_pitch = default_dst_pitch; - - /* TODO: handle vmap in I/O memory here */ - if (dst[0].is_iomem) - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, vmap[0].vaddr, fb, - clip, false, drm_fb_xrgb8888_to_gray8_line); - else - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb, - clip, false, drm_fb_xrgb8888_to_gray8_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xrgb8888_to_gray8_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); From 504a51d70f86e3b989ca8834691bbac4033b6f48 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 8 Aug 2022 14:54:06 +0200 Subject: [PATCH 269/396] drm/format-helper: Rename parameter vmap to src Rename the parameter vmap to src in all functions. The parameter contains the locations of the source data and the new name says that. v3: * fix typo in commit message Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220808125406.20752-15-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 106 ++++++++++++++-------------- include/drm/drm_format_helper.h | 18 ++--- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 0fec3b68db95..56642816fdff 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -132,7 +132,7 @@ static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsign /* TODO: Make this function work with multi-plane formats. */ static int drm_fb_xfrm(struct iosys_map *dst, const unsigned int *dst_pitch, const u8 *dst_pixsize, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool vaddr_cached_hint, void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) { @@ -143,13 +143,13 @@ static int drm_fb_xfrm(struct iosys_map *dst, if (!dst_pitch) dst_pitch = default_dst_pitch; - /* TODO: handle vmap in I/O memory here */ + /* TODO: handle src in I/O memory here */ if (dst[0].is_iomem) return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0], - vmap[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); + src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); else return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0], - vmap[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); + src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); } /** @@ -157,13 +157,13 @@ static int drm_fb_xfrm(struct iosys_map *dst, * @dst: Array of destination buffers * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of source buffers + * @src: Array of source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * This function copies parts of a framebuffer to display memory. Destination and * framebuffer formats must match. No conversion takes place. The parameters @dst, - * @dst_pitch and @vmap refer to arrays. Each array must have at least as many entries + * @dst_pitch and @src refer to arrays. Each array must have at least as many entries * as there are planes in @fb's format. Each entry stores the value for the format's * respective color plane at the same index. * @@ -171,7 +171,7 @@ static int drm_fb_xfrm(struct iosys_map *dst, * top-left corner). */ void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { @@ -190,16 +190,16 @@ void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8); unsigned int dst_pitch_i = dst_pitch[i]; struct iosys_map dst_i = dst[i]; - struct iosys_map vmap_i = vmap[i]; + struct iosys_map src_i = src[i]; if (!dst_pitch_i) dst_pitch_i = len_i; - iosys_map_incr(&vmap_i, clip_offset(clip, fb->pitches[i], cpp_i)); + iosys_map_incr(&src_i, clip_offset(clip, fb->pitches[i], cpp_i)); for (y = 0; y < lines; y++) { - /* TODO: handle vmap_i in I/O memory here */ - iosys_map_memcpy_to(&dst_i, 0, vmap_i.vaddr, len_i); - iosys_map_incr(&vmap_i, fb->pitches[i]); + /* TODO: handle src_i in I/O memory here */ + iosys_map_memcpy_to(&dst_i, 0, src_i.vaddr, len_i); + iosys_map_incr(&src_i, fb->pitches[i]); iosys_map_incr(&dst_i, dst_pitch_i); } } @@ -231,14 +231,14 @@ static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels * @dst: Array of destination buffers * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of source buffers + * @src: Array of source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @cached: Source buffer is mapped cached (eg. not write-combined) * * This function copies parts of a framebuffer to display memory and swaps per-pixel * bytes during the process. Destination and framebuffer formats must match. The - * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at * least as many entries as there are planes in @fb's format. Each entry stores the * value for the format's respective color plane at the same index. If @cached is * false a temporary buffer is used to cache one pixel line at a time to speed up @@ -248,7 +248,7 @@ static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels * top-left corner). */ void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool cached) { const struct drm_format_info *format = fb->format; @@ -268,7 +268,7 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, return; } - drm_fb_xfrm(dst, dst_pitch, &cpp, vmap, fb, clip, cached, swab_line); + drm_fb_xfrm(dst, dst_pitch, &cpp, src, fb, clip, cached, swab_line); } EXPORT_SYMBOL(drm_fb_swab); @@ -292,13 +292,13 @@ static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigne * @dst: Array of RGB332 destination buffers * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of XRGB8888 source buffers + * @src: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * This function copies parts of a framebuffer to display memory and converts the * color format during the process. Destination and framebuffer formats must match. The - * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at * least as many entries as there are planes in @fb's format. Each entry stores the * value for the format's respective color plane at the same index. * @@ -308,14 +308,14 @@ static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigne * Drivers can use this function for RGB332 devices that don't support XRGB8888 natively. */ void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1, }; - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, drm_fb_xrgb8888_to_rgb332_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); @@ -360,14 +360,14 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, * @dst: Array of RGB565 destination buffers * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of XRGB8888 source buffer + * @src: Array of XRGB8888 source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @swab: Swap bytes * * This function copies parts of a framebuffer to display memory and converts the * color format during the process. Destination and framebuffer formats must match. The - * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at * least as many entries as there are planes in @fb's format. Each entry stores the * value for the format's respective color plane at the same index. * @@ -377,7 +377,7 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, * Drivers can use this function for RGB565 devices that don't support XRGB8888 natively. */ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool swab) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { @@ -391,7 +391,7 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi else xfrm_line = drm_fb_xrgb8888_to_rgb565_line; - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, xfrm_line); + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, xfrm_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); @@ -415,13 +415,13 @@ static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigne * @dst: Array of RGB888 destination buffers * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of XRGB8888 source buffers + * @src: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * This function copies parts of a framebuffer to display memory and converts the * color format during the process. Destination and framebuffer formats must match. The - * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at * least as many entries as there are planes in @fb's format. Each entry stores the * value for the format's respective color plane at the same index. * @@ -432,14 +432,14 @@ static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigne * support XRGB8888. */ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 3, }; - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, drm_fb_xrgb8888_to_rgb888_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); @@ -463,7 +463,7 @@ static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne } static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { @@ -471,7 +471,7 @@ static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int 4, }; - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, drm_fb_rgb565_to_xrgb8888_line); } @@ -491,7 +491,7 @@ static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne } static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { @@ -499,7 +499,7 @@ static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int 4, }; - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, drm_fb_rgb888_to_xrgb8888_line); } @@ -526,13 +526,13 @@ static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, un * @dst: Array of XRGB2101010 destination buffers * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of XRGB8888 source buffers + * @src: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * This function copies parts of a framebuffer to display memory and converts the * color format during the process. Destination and framebuffer formats must match. The - * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at * least as many entries as there are planes in @fb's format. Each entry stores the * value for the format's respective color plane at the same index. * @@ -543,14 +543,14 @@ static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, un * natively. */ void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 4, }; - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, drm_fb_xrgb8888_to_xrgb2101010_line); } @@ -576,13 +576,13 @@ static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned * @dst: Array of 8-bit grayscale destination buffers * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of XRGB8888 source buffers + * @src: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * This function copies parts of a framebuffer to display memory and converts the * color format during the process. Destination and framebuffer formats must match. The - * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at * least as many entries as there are planes in @fb's format. Each entry stores the * value for the format's respective color plane at the same index. * @@ -597,14 +597,14 @@ static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned * ITU BT.601 is being used for the RGB -> luma (brightness) conversion. */ void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1, }; - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, vmap, fb, clip, false, + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, drm_fb_xrgb8888_to_gray8_line); } EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); @@ -615,14 +615,14 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. * @dst_format: FOURCC code of the display's color format - * @vmap: The framebuffer memory to copy from + * @src: The framebuffer memory to copy from * @fb: The framebuffer to copy from * @clip: Clip rectangle area to copy * * This function copies parts of a framebuffer to display memory. If the * formats of the display and the framebuffer mismatch, the blit function * will attempt to convert between them during the process. The parameters @dst, - * @dst_pitch and @vmap refer to arrays. Each array must have at least as many + * @dst_pitch and @src refer to arrays. Each array must have at least as many * entries as there are planes in @dst_format's format. Each entry stores the * value for the format's respective color plane at the same index. * @@ -635,7 +635,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); * a negative error code otherwise. */ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { uint32_t fb_format = fb->format->format; @@ -651,30 +651,30 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d dst_format = DRM_FORMAT_XRGB2101010; if (dst_format == fb_format) { - drm_fb_memcpy(dst, dst_pitch, vmap, fb, clip); + drm_fb_memcpy(dst, dst_pitch, src, fb, clip); return 0; } else if (dst_format == DRM_FORMAT_RGB565) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, vmap, fb, clip, false); + drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false); return 0; } } else if (dst_format == DRM_FORMAT_RGB888) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, vmap, fb, clip); + drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB8888) { if (fb_format == DRM_FORMAT_RGB888) { - drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, vmap, fb, clip); + drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, src, fb, clip); return 0; } else if (fb_format == DRM_FORMAT_RGB565) { - drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, vmap, fb, clip); + drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, src, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB2101010) { if (fb_format == DRM_FORMAT_XRGB8888) { - drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, vmap, fb, clip); + drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip); return 0; } } @@ -708,13 +708,13 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int * @dst: Array of monochrome destination buffers (0=black, 1=white) * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines * within @dst; can be NULL if scanlines are stored next to each other. - * @vmap: Array of XRGB8888 source buffers + * @src: Array of XRGB8888 source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * This function copies parts of a framebuffer to display memory and converts the * color format during the process. Destination and framebuffer formats must match. The - * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have at + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at * least as many entries as there are planes in @fb's format. Each entry stores the * value for the format's respective color plane at the same index. * @@ -734,7 +734,7 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int * then the result is converted from grayscale to monochrome. */ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip) { static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { @@ -745,7 +745,7 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc unsigned int cpp = fb->format->cpp[0]; unsigned int len_src32 = linepixels * cpp; struct drm_device *dev = fb->dev; - void *vaddr = vmap[0].vaddr; + void *vaddr = src[0].vaddr; unsigned int dst_pitch_0; unsigned int y; u8 *mono = dst[0].vaddr, *gray8; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 1e1d8f356cc1..caa181194335 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -15,33 +15,33 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info const struct drm_rect *clip); void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool cached); void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool swab); void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *rect); void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); #endif /* __LINUX_DRM_FORMAT_HELPER_H */ From acd45c56790a3b558b0b0081678a20b0a0d89b0f Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 4 Aug 2022 09:58:23 +0200 Subject: [PATCH 270/396] drm/udl: Replace semaphore with a simple wait queue UDL driver uses a semaphore for controlling the emptiness of FIFO in a slightly funky way. This patch replaces it with a wait queue and controls the emptiness with the standard wait_event*() macro instead, which is a more straightforward implementation. While we are at it, drop the dead code for delayed semaphore down, too. Tested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220804075826.27036-2-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.h | 11 +++-- drivers/gpu/drm/udl/udl_main.c | 84 ++++++++++------------------------ 2 files changed, 31 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index cc16a13316e4..e008686ec738 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -34,14 +34,13 @@ struct udl_device; struct urb_node { struct list_head entry; struct udl_device *dev; - struct delayed_work release_urb_work; struct urb *urb; }; struct urb_list { struct list_head list; spinlock_t lock; - struct semaphore limit_sem; + wait_queue_head_t sleep; int available; int count; size_t size; @@ -75,7 +74,13 @@ static inline struct usb_device *udl_to_usb_device(struct udl_device *udl) int udl_modeset_init(struct drm_device *dev); struct drm_connector *udl_connector_init(struct drm_device *dev); -struct urb *udl_get_urb(struct drm_device *dev); +struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout); + +#define GET_URB_TIMEOUT HZ +static inline struct urb *udl_get_urb(struct drm_device *dev) +{ + return udl_get_urb_timeout(dev, GET_URB_TIMEOUT); +} int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); void udl_urb_completion(struct urb *urb); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 853f147036f6..67fd41e59b80 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -23,9 +23,6 @@ #define WRITES_IN_FLIGHT (4) #define MAX_VENDOR_DESCRIPTOR_SIZE 256 -#define GET_URB_TIMEOUT HZ -#define FREE_URB_TIMEOUT (HZ*2) - static int udl_parse_vendor_descriptor(struct udl_device *udl) { struct usb_device *udev = udl_to_usb_device(udl); @@ -119,14 +116,6 @@ static int udl_select_std_channel(struct udl_device *udl) return ret < 0 ? ret : 0; } -static void udl_release_urb_work(struct work_struct *work) -{ - struct urb_node *unode = container_of(work, struct urb_node, - release_urb_work.work); - - up(&unode->dev->urbs.limit_sem); -} - void udl_urb_completion(struct urb *urb) { struct urb_node *unode = urb->context; @@ -150,23 +139,13 @@ void udl_urb_completion(struct urb *urb) udl->urbs.available++; spin_unlock_irqrestore(&udl->urbs.lock, flags); -#if 0 - /* - * When using fb_defio, we deadlock if up() is called - * while another is waiting. So queue to another process. - */ - if (fb_defio) - schedule_delayed_work(&unode->release_urb_work, 0); - else -#endif - up(&udl->urbs.limit_sem); + wake_up(&udl->urbs.sleep); } static void udl_free_urb_list(struct drm_device *dev) { struct udl_device *udl = to_udl(dev); int count = udl->urbs.count; - struct list_head *node; struct urb_node *unode; struct urb *urb; @@ -174,23 +153,15 @@ static void udl_free_urb_list(struct drm_device *dev) /* keep waiting and freeing, until we've got 'em all */ while (count--) { - down(&udl->urbs.limit_sem); - - spin_lock_irq(&udl->urbs.lock); - - node = udl->urbs.list.next; /* have reserved one with sem */ - list_del_init(node); - - spin_unlock_irq(&udl->urbs.lock); - - unode = list_entry(node, struct urb_node, entry); - urb = unode->urb; - + urb = udl_get_urb_timeout(dev, MAX_SCHEDULE_TIMEOUT); + if (WARN_ON(!urb)) + break; + unode = urb->context; /* Free each separately allocated piece */ usb_free_coherent(urb->dev, udl->urbs.size, urb->transfer_buffer, urb->transfer_dma); usb_free_urb(urb); - kfree(node); + kfree(unode); } udl->urbs.count = 0; } @@ -210,7 +181,7 @@ retry: udl->urbs.size = size; INIT_LIST_HEAD(&udl->urbs.list); - sema_init(&udl->urbs.limit_sem, 0); + init_waitqueue_head(&udl->urbs.sleep); udl->urbs.count = 0; udl->urbs.available = 0; @@ -220,9 +191,6 @@ retry: break; unode->dev = udl; - INIT_DELAYED_WORK(&unode->release_urb_work, - udl_release_urb_work); - urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { kfree(unode); @@ -250,7 +218,6 @@ retry: list_add_tail(&unode->entry, &udl->urbs.list); - up(&udl->urbs.limit_sem); udl->urbs.count++; udl->urbs.available++; } @@ -260,36 +227,31 @@ retry: return udl->urbs.count; } -struct urb *udl_get_urb(struct drm_device *dev) +struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout) { struct udl_device *udl = to_udl(dev); - int ret = 0; - struct list_head *entry; - struct urb_node *unode; - struct urb *urb = NULL; + struct urb_node *unode = NULL; + + if (!udl->urbs.count) + return NULL; /* Wait for an in-flight buffer to complete and get re-queued */ - ret = down_timeout(&udl->urbs.limit_sem, GET_URB_TIMEOUT); - if (ret) { - DRM_INFO("wait for urb interrupted: %x available: %d\n", - ret, udl->urbs.available); - goto error; + spin_lock_irq(&udl->urbs.lock); + if (!wait_event_lock_irq_timeout(udl->urbs.sleep, + !list_empty(&udl->urbs.list), + udl->urbs.lock, timeout)) { + DRM_INFO("wait for urb interrupted: available: %d\n", + udl->urbs.available); + goto unlock; } - spin_lock_irq(&udl->urbs.lock); - - BUG_ON(list_empty(&udl->urbs.list)); /* reserved one with limit_sem */ - entry = udl->urbs.list.next; - list_del_init(entry); + unode = list_first_entry(&udl->urbs.list, struct urb_node, entry); + list_del_init(&unode->entry); udl->urbs.available--; +unlock: spin_unlock_irq(&udl->urbs.lock); - - unode = list_entry(entry, struct urb_node, entry); - urb = unode->urb; - -error: - return urb; + return unode ? unode->urb : NULL; } int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) From 0f7dc324b2e9e55db9323302f944fd952dbed967 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 4 Aug 2022 09:58:24 +0200 Subject: [PATCH 271/396] drm/udl: Sync pending URBs at suspend / disconnect We need to wait for finishing to process the all URBs after disabling the pipe; otherwise pending URBs may stray at suspend/resume, leading to a possible memory corruption in a worst case. Tested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220804075826.27036-3-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.h | 1 + drivers/gpu/drm/udl/udl_main.c | 17 +++++++++++++++++ drivers/gpu/drm/udl/udl_modeset.c | 2 ++ 3 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index e008686ec738..f01e50c5b7b7 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -83,6 +83,7 @@ static inline struct urb *udl_get_urb(struct drm_device *dev) } int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); +int udl_sync_pending_urbs(struct drm_device *dev); void udl_urb_completion(struct urb *urb); int udl_init(struct udl_device *udl); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 67fd41e59b80..93615648414b 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -270,6 +270,23 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) return ret; } +/* wait until all pending URBs have been processed */ +int udl_sync_pending_urbs(struct drm_device *dev) +{ + struct udl_device *udl = to_udl(dev); + int ret = 0; + + spin_lock_irq(&udl->urbs.lock); + /* 2 seconds as a sane timeout */ + if (!wait_event_lock_irq_timeout(udl->urbs.sleep, + udl->urbs.available == udl->urbs.count, + udl->urbs.lock, + msecs_to_jiffies(2000))) + ret = -ETIMEDOUT; + spin_unlock_irq(&udl->urbs.lock); + return ret; +} + int udl_init(struct udl_device *udl) { struct drm_device *dev = &udl->drm; diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index e67c40a48fb4..50025606b6ad 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -408,6 +408,8 @@ udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) buf = udl_dummy_render(buf); udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer); + + udl_sync_pending_urbs(dev); } static void From e25d5954264d1871ab2792c7ca2298b811462500 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 4 Aug 2022 09:58:25 +0200 Subject: [PATCH 272/396] drm/udl: Kill pending URBs at suspend and disconnect At both suspend and disconnect, we should rather cancel the pending URBs immediately. For the suspend case, the display will be turned off, so it makes no sense to process the rendering. And for the disconnect case, the device may be no longer accessible, hence we shouldn't do any submission. Tested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220804075826.27036-4-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.h | 2 ++ drivers/gpu/drm/udl/udl_main.c | 25 ++++++++++++++++++++++--- drivers/gpu/drm/udl/udl_modeset.c | 2 ++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index f01e50c5b7b7..28aaf75d71cf 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -39,6 +39,7 @@ struct urb_node { struct urb_list { struct list_head list; + struct list_head in_flight; spinlock_t lock; wait_queue_head_t sleep; int available; @@ -84,6 +85,7 @@ static inline struct urb *udl_get_urb(struct drm_device *dev) int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); int udl_sync_pending_urbs(struct drm_device *dev); +void udl_kill_pending_urbs(struct drm_device *dev); void udl_urb_completion(struct urb *urb); int udl_init(struct udl_device *udl); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 93615648414b..47204b7eb10e 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -135,7 +135,7 @@ void udl_urb_completion(struct urb *urb) urb->transfer_buffer_length = udl->urbs.size; /* reset to actual */ spin_lock_irqsave(&udl->urbs.lock, flags); - list_add_tail(&unode->entry, &udl->urbs.list); + list_move(&unode->entry, &udl->urbs.list); udl->urbs.available++; spin_unlock_irqrestore(&udl->urbs.lock, flags); @@ -180,6 +180,7 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) retry: udl->urbs.size = size; INIT_LIST_HEAD(&udl->urbs.list); + INIT_LIST_HEAD(&udl->urbs.in_flight); init_waitqueue_head(&udl->urbs.sleep); udl->urbs.count = 0; @@ -246,7 +247,7 @@ struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout) } unode = list_first_entry(&udl->urbs.list, struct urb_node, entry); - list_del_init(&unode->entry); + list_move(&unode->entry, &udl->urbs.in_flight); udl->urbs.available--; unlock: @@ -279,7 +280,7 @@ int udl_sync_pending_urbs(struct drm_device *dev) spin_lock_irq(&udl->urbs.lock); /* 2 seconds as a sane timeout */ if (!wait_event_lock_irq_timeout(udl->urbs.sleep, - udl->urbs.available == udl->urbs.count, + list_empty(&udl->urbs.in_flight), udl->urbs.lock, msecs_to_jiffies(2000))) ret = -ETIMEDOUT; @@ -287,6 +288,23 @@ int udl_sync_pending_urbs(struct drm_device *dev) return ret; } +/* kill pending URBs */ +void udl_kill_pending_urbs(struct drm_device *dev) +{ + struct udl_device *udl = to_udl(dev); + struct urb_node *unode; + + spin_lock_irq(&udl->urbs.lock); + while (!list_empty(&udl->urbs.in_flight)) { + unode = list_first_entry(&udl->urbs.in_flight, + struct urb_node, entry); + spin_unlock_irq(&udl->urbs.lock); + usb_kill_urb(unode->urb); + spin_lock_irq(&udl->urbs.lock); + } + spin_unlock_irq(&udl->urbs.lock); +} + int udl_init(struct udl_device *udl) { struct drm_device *dev = &udl->drm; @@ -335,6 +353,7 @@ int udl_drop_usb(struct drm_device *dev) { struct udl_device *udl = to_udl(dev); + udl_kill_pending_urbs(dev); udl_free_urb_list(dev); put_device(udl->dmadev); udl->dmadev = NULL; diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 50025606b6ad..169110d8fc2e 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -397,6 +397,8 @@ udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) struct urb *urb; char *buf; + udl_kill_pending_urbs(dev); + urb = udl_get_urb(dev); if (!urb) return; From 7350b2a3fbc6956b2b2234f6d27d030c70b451bb Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 4 Aug 2022 09:58:26 +0200 Subject: [PATCH 273/396] drm/udl: Replace BUG_ON() with WARN_ON() BUG_ON() is a tasteless choice as a sanity check for a driver like UDL that isn't really a core code. Replace with WARN_ON() and proper error handling instead. Tested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220804075826.27036-5-tiwai@suse.de --- drivers/gpu/drm/udl/udl_main.c | 3 ++- drivers/gpu/drm/udl/udl_transfer.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 47204b7eb10e..fdafbf8f3c3c 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -260,7 +260,8 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) struct udl_device *udl = to_udl(dev); int ret; - BUG_ON(len > udl->urbs.size); + if (WARN_ON(len > udl->urbs.size)) + return -EINVAL; urb->transfer_buffer_length = len; /* set to actual payload len */ ret = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index 971927669d6b..176ef2a6a731 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -220,7 +220,8 @@ int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; - BUG_ON(!(log_bpp == 1 || log_bpp == 2)); + if (WARN_ON(!(log_bpp == 1 || log_bpp == 2))) + return -EINVAL; line_start = (u8 *) (front + byte_offset); next_pixel = line_start; From bcfa6be2ee21b8ff85fa8f51493c8e585e3ab265 Mon Sep 17 00:00:00 2001 From: XueBing Chen <chenxuebing@jari.cn> Date: Fri, 1 Jul 2022 19:26:07 +0800 Subject: [PATCH 274/396] dma-buf/sync_file: use strscpy to replace strlcpy The strlcpy should not be used because it doesn't limit the source length. Preferred is strscpy. Signed-off-by: XueBing Chen <chenxuebing@jari.cn> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/6aad3bff.d1a.181b982d1b1.Coremail.chenxuebing@jari.cn --- drivers/dma-buf/sync_file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 3ebec19a8e02..af57799c86ce 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -132,7 +132,7 @@ EXPORT_SYMBOL(sync_file_get_fence); char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len) { if (sync_file->user_name[0]) { - strlcpy(buf, sync_file->user_name, len); + strscpy(buf, sync_file->user_name, len); } else { struct dma_fence *fence = sync_file->fence; @@ -172,7 +172,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, return NULL; } sync_file->fence = fence; - strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name)); + strscpy(sync_file->user_name, name, sizeof(sync_file->user_name)); return sync_file; } @@ -262,9 +262,9 @@ err_put_fd: static int sync_fill_fence_info(struct dma_fence *fence, struct sync_fence_info *info) { - strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), + strscpy(info->obj_name, fence->ops->get_timeline_name(fence), sizeof(info->obj_name)); - strlcpy(info->driver_name, fence->ops->get_driver_name(fence), + strscpy(info->driver_name, fence->ops->get_driver_name(fence), sizeof(info->driver_name)); info->status = dma_fence_get_status(fence); From 5fa9e16191204b6ead0c31e8f3b6ef92ddd8183e Mon Sep 17 00:00:00 2001 From: Lucas Stach <l.stach@pengutronix.de> Date: Wed, 6 Jul 2022 15:28:10 +0200 Subject: [PATCH 275/396] drm/bridge: tc358767: don't fixup mode sync polarity There is no need to enforce a specific sync signal polarity on the DPI interface, as we can simply tell the TC358767 which polarities it should expect on the input interface. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Marco Felsch <m.felsch@pengutronix.de> Reviewed-by: Marek Vasut <marex@denx.de> Tested-by: Marek Vasut <marex@denx.de> Signed-off-by: Marek Vasut <marex@denx.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220706132812.2171250-1-l.stach@pengutronix.de --- drivers/gpu/drm/bridge/tc358767.c | 54 +++++++++++-------------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 1dc107f13645..578aca2fe9f9 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -889,6 +889,7 @@ static int tc_set_edp_video_mode(struct tc_data *tc, u32 dp0_syncval; u32 bits_per_pixel = 24; u32 in_bw, out_bw; + u32 dpipxlfmt; /* * Recommended maximum number of symbols transferred in a transfer unit: @@ -938,10 +939,15 @@ static int tc_set_edp_video_mode(struct tc_data *tc, if (ret) return ret; - ret = regmap_write(tc->regmap, DPIPXLFMT, - VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | - DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | - DPI_BPP_RGB888); + dpipxlfmt = DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888; + + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + dpipxlfmt |= VS_POL_ACTIVE_LOW; + + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + dpipxlfmt |= HS_POL_ACTIVE_LOW; + + ret = regmap_write(tc->regmap, DPIPXLFMT, dpipxlfmt); if (ret) return ret; @@ -1496,41 +1502,16 @@ tc_edp_bridge_atomic_disable(struct drm_bridge *bridge, dev_err(tc->dev, "main link disable error: %d\n", ret); } -static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adj) -{ - /* Fixup sync polarities, both hsync and vsync are active low */ - adj->flags = mode->flags; - adj->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC); - adj->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); - - return true; -} - -static int tc_common_atomic_check(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state, - const unsigned int max_khz) -{ - tc_bridge_mode_fixup(bridge, &crtc_state->mode, - &crtc_state->adjusted_mode); - - if (crtc_state->adjusted_mode.clock > max_khz) - return -EINVAL; - - return 0; -} - static int tc_dpi_atomic_check(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { /* DSI->DPI interface clock limitation: upto 100 MHz */ - return tc_common_atomic_check(bridge, bridge_state, crtc_state, - conn_state, 100000); + if (crtc_state->adjusted_mode.clock > 100000) + return -EINVAL; + + return 0; } static int tc_edp_atomic_check(struct drm_bridge *bridge, @@ -1539,8 +1520,10 @@ static int tc_edp_atomic_check(struct drm_bridge *bridge, struct drm_connector_state *conn_state) { /* DPI->(e)DP interface clock limitation: upto 154 MHz */ - return tc_common_atomic_check(bridge, bridge_state, crtc_state, - conn_state, 154000); + if (crtc_state->adjusted_mode.clock > 154000) + return -EINVAL; + + return 0; } static enum drm_mode_status @@ -1783,7 +1766,6 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = { .atomic_check = tc_edp_atomic_check, .atomic_enable = tc_edp_bridge_atomic_enable, .atomic_disable = tc_edp_bridge_atomic_disable, - .mode_fixup = tc_bridge_mode_fixup, .detect = tc_bridge_detect, .get_edid = tc_get_edid, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, From ea6490b02240bd7939a3a13bc8d3f25046c01585 Mon Sep 17 00:00:00 2001 From: Lucas Stach <l.stach@pengutronix.de> Date: Wed, 6 Jul 2022 15:28:11 +0200 Subject: [PATCH 276/396] drm/bridge: tc358767: increase CLRSIPO count The current CLRSIPO count is marginal and does not work with high DSI clock rates. Increase it a bit to allow the DSI link to work at up to 1Gbps lane speed. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Marek Vasut <marex@denx.de> Tested-by: Marek Vasut <marex@denx.de> Signed-off-by: Marek Vasut <marex@denx.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220706132812.2171250-2-l.stach@pengutronix.de --- drivers/gpu/drm/bridge/tc358767.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 578aca2fe9f9..2f6cb0c6902f 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1258,10 +1258,10 @@ static int tc_dsi_rx_enable(struct tc_data *tc) u32 value; int ret; - regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 3); - regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 3); - regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 3); - regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 3); + regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 5); + regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 5); + regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 5); + regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 5); regmap_write(tc->regmap, PPI_D0S_ATMR, 0); regmap_write(tc->regmap, PPI_D1S_ATMR, 0); regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE); From 8759464d7b6309e23df95f12064a120422d6f780 Mon Sep 17 00:00:00 2001 From: Lucas Stach <l.stach@pengutronix.de> Date: Wed, 6 Jul 2022 15:28:12 +0200 Subject: [PATCH 277/396] drm/bridge: tc358767: disable main link PHYs on main link disable Disable the main link PHYs and put them into reset when the main link is disabled. When the PHYs stay enabled while the rest of the DP link circuits are disabled there is some noise on the data lanes, which some displays try to lock onto, waking them up from their low power state. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Robert Foss <robert.foss@linaro.org> Reviewed-by: Marek Vasut <marex@denx.de> Tested-by: Marek Vasut <marex@denx.de> Signed-off-by: Marek Vasut <marex@denx.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220706132812.2171250-3-l.stach@pengutronix.de --- drivers/gpu/drm/bridge/tc358767.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 2f6cb0c6902f..baaed4d37911 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1250,7 +1250,13 @@ static int tc_main_link_disable(struct tc_data *tc) if (ret) return ret; - return regmap_write(tc->regmap, DP0CTL, 0); + ret = regmap_write(tc->regmap, DP0CTL, 0); + if (ret) + return ret; + + return regmap_update_bits(tc->regmap, DP_PHY_CTRL, + PHY_M0_RST | PHY_M1_RST | PHY_M0_EN, + PHY_M0_RST | PHY_M1_RST); } static int tc_dsi_rx_enable(struct tc_data *tc) From e0686dc6f2252e009c455fe99e2ce9d62a60eb47 Mon Sep 17 00:00:00 2001 From: Liang He <windhl@126.com> Date: Mon, 11 Jul 2022 21:15:50 +0800 Subject: [PATCH 278/396] drm:pl111: Add of_node_put() when breaking out of for_each_available_child_of_node() The reference 'child' in the iteration of for_each_available_child_of_node() is only escaped out into a local variable which is only used to check its value. So we still need to the of_node_put() when breaking of the for_each_available_child_of_node() which will automatically increase and decrease the refcount. Fixes: ca454bd42dc2 ("drm/pl111: Support the Versatile Express") Signed-off-by: Liang He <windhl@126.com> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220711131550.361350-1-windhl@126.com --- drivers/gpu/drm/pl111/pl111_versatile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c index efb01a554574..1b436b75fd39 100644 --- a/drivers/gpu/drm/pl111/pl111_versatile.c +++ b/drivers/gpu/drm/pl111/pl111_versatile.c @@ -404,6 +404,7 @@ static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np, if (of_device_is_compatible(child, "arm,pl111")) { has_coretile_clcd = true; ct_clcd = child; + of_node_put(child); break; } if (of_device_is_compatible(child, "arm,hdlcd")) { From 82068edeb5090b6f999457483623b39b6546ef74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com> Date: Tue, 19 Jul 2022 12:56:58 +0300 Subject: [PATCH 279/396] drm: New function to get luminance range based on static hdr metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split luminance min/max calculation using static hdr metadata from drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:update_connector_ext_caps into drm/drm_edid.c and use it during edid parsing. Calculated range is stored into connector->display_info->luminance_range. Add new data structure (drm_luminance_range_inf) to store luminance range calculated using data from EDID's static hdr metadata block. Add this new struct as a part of drm_display_info struct. v3: Squashed adding drm_luminance_range_info patch here v2: Calculate range during edid parsing Cc: Roman Li <roman.li@amd.com> Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Cc: Harry Wentland <harry.wentland@amd.com> Cc: Lyude Paul <lyude@redhat.com> Cc: Mika Kahola <mika.kahola@intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Manasi Navare <manasi.d.navare@intel.com> Signed-off-by: Jouni Högander <jouni.hogander@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220719095700.14923-2-jouni.hogander@intel.com --- drivers/gpu/drm/drm_edid.c | 52 ++++++++++++++++++++++++++++++++++++- include/drm/drm_connector.h | 21 +++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index bbc25e3b7220..90a5e26eafa8 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5165,6 +5165,51 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode) mode->clock = clock; } +static void drm_calculate_luminance_range(struct drm_connector *connector) +{ + struct hdr_static_metadata *hdr_metadata = &connector->hdr_sink_metadata.hdmi_type1; + struct drm_luminance_range_info *luminance_range = + &connector->display_info.luminance_range; + static const u8 pre_computed_values[] = { + 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, + 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98 + }; + u32 max_avg, min_cll, max, min, q, r; + + if (!(hdr_metadata->metadata_type & BIT(HDMI_STATIC_METADATA_TYPE1))) + return; + + max_avg = hdr_metadata->max_fall; + min_cll = hdr_metadata->min_cll; + + /* + * From the specification (CTA-861-G), for calculating the maximum + * luminance we need to use: + * Luminance = 50*2**(CV/32) + * Where CV is a one-byte value. + * For calculating this expression we may need float point precision; + * to avoid this complexity level, we take advantage that CV is divided + * by a constant. From the Euclids division algorithm, we know that CV + * can be written as: CV = 32*q + r. Next, we replace CV in the + * Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just + * need to pre-compute the value of r/32. For pre-computing the values + * We just used the following Ruby line: + * (0...32).each {|cv| puts (50*2**(cv/32.0)).round} + * The results of the above expressions can be verified at + * pre_computed_values. + */ + q = max_avg >> 5; + r = max_avg % 32; + max = (1 << q) * pre_computed_values[r]; + + /* min luminance: maxLum * (CV/255)^2 / 100 */ + q = DIV_ROUND_CLOSEST(min_cll, 255); + min = max * DIV_ROUND_CLOSEST((q * q), 100); + + luminance_range->min_luminance = min; + luminance_range->max_luminance = max; +} + static uint8_t eotf_supported(const u8 *edid_ext) { return edid_ext[2] & @@ -5196,8 +5241,12 @@ drm_parse_hdr_metadata_block(struct drm_connector *connector, const u8 *db) connector->hdr_sink_metadata.hdmi_type1.max_cll = db[4]; if (len >= 5) connector->hdr_sink_metadata.hdmi_type1.max_fall = db[5]; - if (len >= 6) + if (len >= 6) { connector->hdr_sink_metadata.hdmi_type1.min_cll = db[6]; + + /* Calculate only when all values are available */ + drm_calculate_luminance_range(connector); + } } static void @@ -6101,6 +6150,7 @@ static void drm_reset_display_info(struct drm_connector *connector) info->non_desktop = 0; memset(&info->monitor_range, 0, sizeof(info->monitor_range)); + memset(&info->luminance_range, 0, sizeof(info->luminance_range)); info->mso_stream_count = 0; info->mso_pixel_overlap = 0; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 2c6fa746efac..248206bbd975 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -323,6 +323,22 @@ struct drm_monitor_range_info { u8 max_vfreq; }; +/** + * struct drm_luminance_range_info - Panel's luminance range for + * &drm_display_info. Calculated using data in EDID + * + * This struct is used to store a luminance range supported by panel + * as calculated using data from EDID's static hdr metadata. + * + * @min_luminance: This is the min supported luminance value + * + * @max_luminance: This is the max supported luminance value + */ +struct drm_luminance_range_info { + u32 min_luminance; + u32 max_luminance; +}; + /** * enum drm_privacy_screen_status - privacy screen status * @@ -624,6 +640,11 @@ struct drm_display_info { */ struct drm_monitor_range_info monitor_range; + /** + * @luminance_range: Luminance range supported by panel + */ + struct drm_luminance_range_info luminance_range; + /** * @mso_stream_count: eDP Multi-SST Operation (MSO) stream count from * the DisplayID VESA vendor block. 0 for conventional Single-Stream From a61bb3422e8d6ec002dbe288356470540eb5662c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com> Date: Tue, 19 Jul 2022 12:56:59 +0300 Subject: [PATCH 280/396] drm/amdgpu_dm: Rely on split out luminance calculation function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Luminance range calculation was split out into drm_edid.c and is now part of edid parsing. Rely on values calculated during edid parsing and use these for caps->aux_max_input_signal and caps->aux_min_input_signal. v2: Use values calculated during edid parsing Cc: Roman Li <roman.li@amd.com> Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Cc: Harry Wentland <harry.wentland@amd.com> Cc: Lyude Paul <lyude@redhat.com> Cc: Mika Kahola <mika.kahola@intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Manasi Navare <manasi.d.navare@intel.com> Signed-off-by: Jouni Högander <jouni.hogander@intel.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220719095700.14923-3-jouni.hogander@intel.com --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 35 +++---------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8a3e25d35099..85fdd6baf803 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2813,15 +2813,12 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) { - u32 max_avg, min_cll, max, min, q, r; struct amdgpu_dm_backlight_caps *caps; struct amdgpu_display_manager *dm; struct drm_connector *conn_base; struct amdgpu_device *adev; struct dc_link *link = NULL; - static const u8 pre_computed_values[] = { - 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, - 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; + struct drm_luminance_range_info *luminance_range; int i; if (!aconnector || !aconnector->dc_link) @@ -2843,8 +2840,6 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) caps = &dm->backlight_caps[i]; caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; caps->aux_support = false; - max_avg = conn_base->hdr_sink_metadata.hdmi_type1.max_fall; - min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll; if (caps->ext_caps->bits.oled == 1 /*|| caps->ext_caps->bits.sdr_aux_backlight_control == 1 || @@ -2856,31 +2851,9 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) else if (amdgpu_backlight == 1) caps->aux_support = true; - /* From the specification (CTA-861-G), for calculating the maximum - * luminance we need to use: - * Luminance = 50*2**(CV/32) - * Where CV is a one-byte value. - * For calculating this expression we may need float point precision; - * to avoid this complexity level, we take advantage that CV is divided - * by a constant. From the Euclids division algorithm, we know that CV - * can be written as: CV = 32*q + r. Next, we replace CV in the - * Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just - * need to pre-compute the value of r/32. For pre-computing the values - * We just used the following Ruby line: - * (0...32).each {|cv| puts (50*2**(cv/32.0)).round} - * The results of the above expressions can be verified at - * pre_computed_values. - */ - q = max_avg >> 5; - r = max_avg % 32; - max = (1 << q) * pre_computed_values[r]; - - // min luminance: maxLum * (CV/255)^2 / 100 - q = DIV_ROUND_CLOSEST(min_cll, 255); - min = max * DIV_ROUND_CLOSEST((q * q), 100); - - caps->aux_max_input_signal = max; - caps->aux_min_input_signal = min; + luminance_range = &conn_base->display_info.luminance_range; + caps->aux_min_input_signal = luminance_range->min_luminance; + caps->aux_max_input_signal = luminance_range->max_luminance; } void amdgpu_dm_update_connector_after_detect( From 3bd86801c84f66b4abedde4078e5237937b7576b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com> Date: Tue, 19 Jul 2022 12:57:00 +0300 Subject: [PATCH 281/396] drm/i915: Use luminance range calculated during edid parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using fixed 0 - 512 range use luminance range calculated as a part of edid parsing. As a backup fall back to static 0 - 512. v3: Clean-ups suggested by Jani Nikula v2: Use values calculated during edid parsing Cc: Lyude Paul <lyude@redhat.com> Cc: Mika Kahola <mika.kahola@intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Manasi Navare <manasi.d.navare@intel.com> Signed-off-by: Jouni Högander <jouni.hogander@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220719095700.14923-4-jouni.hogander@intel.com --- .../gpu/drm/i915/display/intel_dp_aux_backlight.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index c92d5bb2326a..83af95bce98d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -278,6 +278,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; + struct drm_luminance_range_info *luminance_range = + &connector->base.display_info.luminance_range; int ret; if (panel->backlight.edp.intel.sdr_uses_aux) { @@ -293,8 +295,17 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi } } - panel->backlight.max = 512; - panel->backlight.min = 0; + if (luminance_range->max_luminance) { + panel->backlight.max = luminance_range->max_luminance; + panel->backlight.min = luminance_range->min_luminance; + } else { + panel->backlight.max = 512; + panel->backlight.min = 0; + } + + drm_dbg_kms(&i915->drm, "Using backlight range %d..%d\n", panel->backlight.min, + panel->backlight.max); + panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe); panel->backlight.enabled = panel->backlight.level != 0; From 3b3510f1bd5c3112811b5b79cae3754fc91d31b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <mairacanal@riseup.net> Date: Fri, 12 Aug 2022 17:57:46 -0300 Subject: [PATCH 282/396] drm/vc4: Drop of_gpio header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver includes the deprecated OF GPIO header <linux/of_gpio.h> yet fail to use symbols from it, so drop the include. Cc: Emma Anholt <emma@anholt.net> Cc: Maxime Ripard <mripard@kernel.org> Signed-off-by: Maíra Canal <mairacanal@riseup.net> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220812205746.609107-6-mairacanal@riseup.net --- drivers/gpu/drm/vc4/vc4_hdmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 6f61a1b8a1a3..84e5a91c2ea7 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -42,7 +42,6 @@ #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/of_address.h> -#include <linux/of_gpio.h> #include <linux/of_platform.h> #include <linux/pm_runtime.h> #include <linux/rational.h> From 8ba9249396bef37cb68be9e8dee7847f1737db9d Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Tue, 16 Aug 2022 14:04:36 -0400 Subject: [PATCH 283/396] drm/nouveau/kms/nv140-: Disable interlacing As it turns out: while Nvidia does actually have interlacing knobs on their GPU still pretty much no current GPUs since Volta actually support it. Trying interlacing on these GPUs will result in NVDisplay being quite unhappy like so: nouveau 0000:1f:00.0: disp: chid 0 stat 00004802 reason 4 [INVALID_ARG] mthd 2008 data 00000001 code 00080000 nouveau 0000:1f:00.0: disp: chid 0 stat 10005080 reason 5 [INVALID_STATE] mthd 0200 data 00000001 code 00000001 So let's fix this by following the same behavior Nvidia's driver does and disable interlacing entirely. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: stable@vger.kernel.org Reviewed-by: Karol Herbst <kherbst@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220816180436.156310-1-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 43a9d1e1cf71..8100c75ee731 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -504,7 +504,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector, connector->interlace_allowed = nv_encoder->caps.dp_interlace; else - connector->interlace_allowed = true; + connector->interlace_allowed = + drm->client.device.info.family < NV_DEVICE_INFO_V0_VOLTA; connector->doublescan_allowed = true; } else if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS || From 8869fa666a9e6782c3c896c1fa57d65adca23249 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Wed, 3 Aug 2022 16:55:20 +0200 Subject: [PATCH 284/396] drm/virtio: remove drm_plane_cleanup() destroy hook drmm_universal_plane_alloc() already registers drm_plane_cleanup() as managed release action via drmm_add_action_or_reset(). Hence, drm_plane_cleanup() should not be set as drm_plane_funcs.destroy hook. Fixes: 7847628862a8 ("drm/virtio: plane: use drm managed resources") Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Danilo Krummrich <dakr@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220803145520.1143208-1-dakr@redhat.com --- drivers/gpu/drm/virtio/virtgpu_plane.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index c599c99f228e..4c09e313bebc 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -69,7 +69,6 @@ uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc) static const struct drm_plane_funcs virtio_gpu_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_plane_cleanup, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, From 0a58d2ae572adaec8d046f8d35b40c2c32ac7468 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas <javierm@redhat.com> Date: Tue, 16 Aug 2022 15:46:12 +0200 Subject: [PATCH 285/396] drm/msm: Make .remove and .shutdown HW shutdown consistent Drivers' .remove and .shutdown callbacks are executed on different code paths. The former is called when a device is removed from the bus, while the latter is called at system shutdown time to quiesce the device. This means that some overlap exists between the two, because both have to take care of properly shutting down the hardware. But currently the logic used in these two callbacks isn't consistent in msm drivers, which could lead to kernel panic. For example, on .remove the component is deleted and its .unbind callback leads to the hardware being shutdown but only if the DRM device has been marked as registered. That check doesn't exist in the .shutdown logic and this can lead to the driver calling drm_atomic_helper_shutdown() for a DRM device that hasn't been properly initialized. A situation like this can happen if drivers for expected sub-devices fail to probe, since the .bind callback will never be executed. If that is the case, drm_atomic_helper_shutdown() will attempt to take mutexes that are only initialized if drm_mode_config_init() is called during a device bind. This bug was attempted to be fixed in commit 623f279c7781 ("drm/msm: fix shutdown hook in case GPU components failed to bind"), but unfortunately it still happens in some cases as the one mentioned above, i.e: systemd-shutdown[1]: Powering off. kvm: exiting hardware virtualization platform wifi-firmware.0: Removing from iommu group 12 platform video-firmware.0: Removing from iommu group 10 ------------[ cut here ]------------ WARNING: CPU: 6 PID: 1 at drivers/gpu/drm/drm_modeset_lock.c:317 drm_modeset_lock_all_ctx+0x3c4/0x3d0 ... Hardware name: Google CoachZ (rev3+) (DT) pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : drm_modeset_lock_all_ctx+0x3c4/0x3d0 lr : drm_modeset_lock_all_ctx+0x48/0x3d0 sp : ffff80000805bb80 x29: ffff80000805bb80 x28: ffff327c00128000 x27: 0000000000000000 x26: 0000000000000000 x25: 0000000000000001 x24: ffffc95d820ec030 x23: ffff327c00bbd090 x22: ffffc95d8215eca0 x21: ffff327c039c5800 x20: ffff327c039c5988 x19: ffff80000805bbe8 x18: 0000000000000034 x17: 000000040044ffff x16: ffffc95d80cac920 x15: 0000000000000000 x14: 0000000000000315 x13: 0000000000000315 x12: 0000000000000000 x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 x8 : ffff80000805bc28 x7 : 0000000000000000 x6 : 0000000000000000 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 x2 : ffff327c00128000 x1 : 0000000000000000 x0 : ffff327c039c59b0 Call trace: drm_modeset_lock_all_ctx+0x3c4/0x3d0 drm_atomic_helper_shutdown+0x70/0x134 msm_drv_shutdown+0x30/0x40 platform_shutdown+0x28/0x40 device_shutdown+0x148/0x350 kernel_power_off+0x38/0x80 __do_sys_reboot+0x288/0x2c0 __arm64_sys_reboot+0x28/0x34 invoke_syscall+0x48/0x114 el0_svc_common.constprop.0+0x44/0xec do_el0_svc+0x2c/0xc0 el0_svc+0x2c/0x84 el0t_64_sync_handler+0x11c/0x150 el0t_64_sync+0x18c/0x190 ---[ end trace 0000000000000000 ]--- Unable to handle kernel NULL pointer dereference at virtual address 0000000000000018 Mem abort info: ESR = 0x0000000096000004 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x04: level 0 translation fault Data abort info: ISV = 0, ISS = 0x00000004 CM = 0, WnR = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=000000010eab1000 [0000000000000018] pgd=0000000000000000, p4d=0000000000000000 Internal error: Oops: 96000004 [#1] PREEMPT SMP ... Hardware name: Google CoachZ (rev3+) (DT) pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : ww_mutex_lock+0x28/0x32c lr : drm_modeset_lock_all_ctx+0x1b0/0x3d0 sp : ffff80000805bb50 x29: ffff80000805bb50 x28: ffff327c00128000 x27: 0000000000000000 x26: 0000000000000000 x25: 0000000000000001 x24: 0000000000000018 x23: ffff80000805bc10 x22: ffff327c039c5ad8 x21: ffff327c039c5800 x20: ffff80000805bbe8 x19: 0000000000000018 x18: 0000000000000034 x17: 000000040044ffff x16: ffffc95d80cac920 x15: 0000000000000000 x14: 0000000000000315 x13: 0000000000000315 x12: 0000000000000000 x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 x8 : ffff80000805bc28 x7 : 0000000000000000 x6 : 0000000000000000 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 x2 : ffff327c00128000 x1 : 0000000000000000 x0 : 0000000000000018 Call trace: ww_mutex_lock+0x28/0x32c drm_modeset_lock_all_ctx+0x1b0/0x3d0 drm_atomic_helper_shutdown+0x70/0x134 msm_drv_shutdown+0x30/0x40 platform_shutdown+0x28/0x40 device_shutdown+0x148/0x350 kernel_power_off+0x38/0x80 __do_sys_reboot+0x288/0x2c0 __arm64_sys_reboot+0x28/0x34 invoke_syscall+0x48/0x114 el0_svc_common.constprop.0+0x44/0xec do_el0_svc+0x2c/0xc0 el0_svc+0x2c/0x84 el0t_64_sync_handler+0x11c/0x150 el0t_64_sync+0x18c/0x190 Code: aa0103f4 d503201f d2800001 aa0103e3 (c8e37c02) ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b Kernel Offset: 0x495d77c00000 from 0xffff800008000000 PHYS_OFFSET: 0xffffcd8500000000 CPU features: 0x800,00c2a015,19801c82 Memory Limit: none ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- Fixes: 9d5cbf5fe46e ("drm/msm: add shutdown support for display platform_driver") Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220816134612.916527-1-javierm@redhat.com --- drivers/gpu/drm/msm/msm_drv.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 1d0bafedd585..226d8d4629d2 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1242,10 +1242,15 @@ void msm_drv_shutdown(struct platform_device *pdev) struct msm_drm_private *priv = platform_get_drvdata(pdev); struct drm_device *drm = priv ? priv->dev : NULL; - if (!priv || !priv->kms) - return; - - drm_atomic_helper_shutdown(drm); + /* + * Shutdown the hw if we're far enough along where things might be on. + * If we run this too early, we'll end up panicking in any variety of + * places. Since we don't register the drm device until late in + * msm_drm_init, drm_dev->registered is used as an indicator that the + * shutdown will be successful. + */ + if (drm && drm->registered) + drm_atomic_helper_shutdown(drm); } static struct platform_driver msm_platform_driver = { From 544432703b2fe73a07f387c0b883da03ffa5671e Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Sat, 20 Aug 2022 00:32:59 -0700 Subject: [PATCH 286/396] drm/ttm: Add new callbacks to ttm res mgr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are adding two new callbacks to ttm resource manager function to handle intersection and compatibility of placement and resources. v2: move the amdgpu and ttm_range_manager changes to separate patches (Christian) v3: rename "intersect" to "intersects" (Matthew) v4: move !place check to the !res if and return false in ttm_resource_compatible() function (Christian) v5: move bits of code from patch number 6 to avoid temporary driver breakup (Christian) Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220820073304.178444-1-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/ttm/ttm_bo.c | 9 ++-- drivers/gpu/drm/ttm/ttm_resource.c | 77 +++++++++++++++++++++++++++++- include/drm/ttm/ttm_resource.h | 40 ++++++++++++++++ 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c1bd006a5525..f066e8124c50 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -518,6 +518,9 @@ out: bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { + struct ttm_resource *res = bo->resource; + struct ttm_device *bdev = bo->bdev; + dma_resv_assert_held(bo->base.resv); if (bo->resource->mem_type == TTM_PL_SYSTEM) return true; @@ -525,11 +528,7 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, /* Don't evict this BO if it's outside of the * requested placement range */ - if (place->fpfn >= (bo->resource->start + bo->resource->num_pages) || - (place->lpfn && place->lpfn <= bo->resource->start)) - return false; - - return true; + return ttm_resource_intersects(bdev, res, place, bo->base.size); } EXPORT_SYMBOL(ttm_bo_eviction_valuable); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 20f9adcc3235..0d1f862a582b 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -253,10 +253,84 @@ void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) } EXPORT_SYMBOL(ttm_resource_free); +/** + * ttm_resource_intersects - test for intersection + * + * @bdev: TTM device structure + * @res: The resource to test + * @place: The placement to test + * @size: How many bytes the new allocation needs. + * + * Test if @res intersects with @place and @size. Used for testing if evictions + * are valueable or not. + * + * Returns true if the res placement intersects with @place and @size. + */ +bool ttm_resource_intersects(struct ttm_device *bdev, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct ttm_resource_manager *man; + + if (!res) + return false; + + if (!place) + return true; + + man = ttm_manager_type(bdev, res->mem_type); + if (!man->func->intersects) { + if (place->fpfn >= (res->start + res->num_pages) || + (place->lpfn && place->lpfn <= res->start)) + return false; + + return true; + } + + return man->func->intersects(man, res, place, size); +} + +/** + * ttm_resource_compatible - test for compatibility + * + * @bdev: TTM device structure + * @res: The resource to test + * @place: The placement to test + * @size: How many bytes the new allocation needs. + * + * Test if @res compatible with @place and @size. + * + * Returns true if the res placement compatible with @place and @size. + */ +bool ttm_resource_compatible(struct ttm_device *bdev, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct ttm_resource_manager *man; + + if (!res || !place) + return false; + + man = ttm_manager_type(bdev, res->mem_type); + if (!man->func->compatible) { + if (res->start < place->fpfn || + (place->lpfn && (res->start + res->num_pages) > place->lpfn)) + return false; + + return true; + } + + return man->func->compatible(man, res, place, size); +} + static bool ttm_resource_places_compat(struct ttm_resource *res, const struct ttm_place *places, unsigned num_placement) { + struct ttm_buffer_object *bo = res->bo; + struct ttm_device *bdev = bo->bdev; unsigned i; if (res->placement & TTM_PL_FLAG_TEMPORARY) @@ -265,8 +339,7 @@ static bool ttm_resource_places_compat(struct ttm_resource *res, for (i = 0; i < num_placement; i++) { const struct ttm_place *heap = &places[i]; - if (res->start < heap->fpfn || (heap->lpfn && - (res->start + res->num_pages) > heap->lpfn)) + if (!ttm_resource_compatible(bdev, res, heap, bo->base.size)) continue; if ((res->mem_type == heap->mem_type) && diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index ca89a48c2460..5afc6d664fde 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -88,6 +88,38 @@ struct ttm_resource_manager_func { void (*free)(struct ttm_resource_manager *man, struct ttm_resource *res); + /** + * struct ttm_resource_manager_func member intersects + * + * @man: Pointer to a memory type manager. + * @res: Pointer to a struct ttm_resource to be checked. + * @place: Placement to check against. + * @size: Size of the check. + * + * Test if @res intersects with @place + @size. Used to judge if + * evictions are valueable or not. + */ + bool (*intersects)(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size); + + /** + * struct ttm_resource_manager_func member compatible + * + * @man: Pointer to a memory type manager. + * @res: Pointer to a struct ttm_resource to be checked. + * @place: Placement to check against. + * @size: Size of the check. + * + * Test if @res compatible with @place + @size. Used to check of + * the need to move the backing store or not. + */ + bool (*compatible)(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size); + /** * struct ttm_resource_manager_func member debug * @@ -329,6 +361,14 @@ int ttm_resource_alloc(struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_resource **res); void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res); +bool ttm_resource_intersects(struct ttm_device *bdev, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size); +bool ttm_resource_compatible(struct ttm_device *bdev, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size); bool ttm_resource_compat(struct ttm_resource *res, struct ttm_placement *placement); void ttm_resource_set_bo(struct ttm_resource *res, From 75ba3121acd58b71ee1d2f6e30ab44748d4397de Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Sat, 20 Aug 2022 00:33:00 -0700 Subject: [PATCH 287/396] drm/ttm: Implement intersect/compatible functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented a new intersect and compatible callback functions to ttm range manager fetching start offset from drm mm range allocator. Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220820073304.178444-2-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/ttm/ttm_range_manager.c | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index d91666721dc6..4cfef2b3514d 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -113,6 +113,37 @@ static void ttm_range_man_free(struct ttm_resource_manager *man, kfree(node); } +static bool ttm_range_man_intersects(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct drm_mm_node *node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; + u32 num_pages = PFN_UP(size); + + /* Don't evict BOs outside of the requested placement range */ + if (place->fpfn >= (node->start + num_pages) || + (place->lpfn && place->lpfn <= node->start)) + return false; + + return true; +} + +static bool ttm_range_man_compatible(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct drm_mm_node *node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; + u32 num_pages = PFN_UP(size); + + if (node->start < place->fpfn || + (place->lpfn && (node->start + num_pages) > place->lpfn)) + return false; + + return true; +} + static void ttm_range_man_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { @@ -126,6 +157,8 @@ static void ttm_range_man_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func ttm_range_manager_func = { .alloc = ttm_range_man_alloc, .free = ttm_range_man_free, + .intersects = ttm_range_man_intersects, + .compatible = ttm_range_man_compatible, .debug = ttm_range_man_debug }; From ded910f368a52b64a3c0eb12da085058b55f61a1 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Sat, 20 Aug 2022 00:33:01 -0700 Subject: [PATCH 288/396] drm/amdgpu: Implement intersect/compatible functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented a new intersect and compatible callback function fetching start offset from backend drm buddy allocator. Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220820073304.178444-3-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 38 +++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 68 ++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 8c6b2284cf56..1f3302aebeff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -204,6 +204,42 @@ void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr) amdgpu_gart_invalidate_tlb(adev); } +/** + * amdgpu_gtt_mgr_intersects - test for intersection + * + * @man: Our manager object + * @res: The resource to test + * @place: The place for the new allocation + * @size: The size of the new allocation + * + * Simplified intersection test, only interesting if we need GART or not. + */ +static bool amdgpu_gtt_mgr_intersects(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); +} + +/** + * amdgpu_gtt_mgr_compatible - test for compatibility + * + * @man: Our manager object + * @res: The resource to test + * @place: The place for the new allocation + * @size: The size of the new allocation + * + * Simplified compatibility test. + */ +static bool amdgpu_gtt_mgr_compatible(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); +} + /** * amdgpu_gtt_mgr_debug - dump VRAM table * @@ -225,6 +261,8 @@ static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = { .alloc = amdgpu_gtt_mgr_new, .free = amdgpu_gtt_mgr_del, + .intersects = amdgpu_gtt_mgr_intersects, + .compatible = amdgpu_gtt_mgr_compatible, .debug = amdgpu_gtt_mgr_debug }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 28ec5f8ac1c1..d1a2619fa89f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -720,6 +720,72 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct amdgpu_vram_mgr *mgr) return atomic64_read(&mgr->vis_usage); } +/** + * amdgpu_vram_mgr_intersects - test each drm buddy block for intersection + * + * @man: TTM memory type manager + * @res: The resource to test + * @place: The place to test against + * @size: Size of the new allocation + * + * Test each drm buddy block for intersection for eviction decision. + */ +static bool amdgpu_vram_mgr_intersects(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res); + struct drm_buddy_block *block; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, &mgr->blocks, link) { + unsigned long fpfn = + amdgpu_vram_mgr_block_start(block) >> PAGE_SHIFT; + unsigned long lpfn = fpfn + + (amdgpu_vram_mgr_block_size(block) >> PAGE_SHIFT); + + if (place->fpfn < lpfn && + (place->lpfn && place->lpfn > fpfn)) + return true; + } + + return false; +} + +/** + * amdgpu_vram_mgr_compatible - test each drm buddy block for compatibility + * + * @man: TTM memory type manager + * @res: The resource to test + * @place: The place to test against + * @size: Size of the new allocation + * + * Test each drm buddy block for placement compatibility. + */ +static bool amdgpu_vram_mgr_compatible(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res); + struct drm_buddy_block *block; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, &mgr->blocks, link) { + unsigned long fpfn = + amdgpu_vram_mgr_block_start(block) >> PAGE_SHIFT; + unsigned long lpfn = fpfn + + (amdgpu_vram_mgr_block_size(block) >> PAGE_SHIFT); + + if (fpfn < place->fpfn || + (place->lpfn && lpfn > place->lpfn)) + return false; + } + + return true; +} + /** * amdgpu_vram_mgr_debug - dump VRAM table * @@ -753,6 +819,8 @@ static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = { .alloc = amdgpu_vram_mgr_new, .free = amdgpu_vram_mgr_del, + .intersects = amdgpu_vram_mgr_intersects, + .compatible = amdgpu_vram_mgr_compatible, .debug = amdgpu_vram_mgr_debug }; From 92b2b55e68c8cb88588073434ff3e3240e98504c Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Sat, 20 Aug 2022 00:33:02 -0700 Subject: [PATCH 289/396] drm/i915: Implement intersect/compatible functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented a new intersect and compatible callback function fetching start offset from drm buddy allocator. v3: move the bits that are specific to buddy_man (Matthew) v4: consider the block size /range (Matthew) Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220820073304.178444-4-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 41 +---------- drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 5a5cf332d8a5..bc9c432edffe 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -361,7 +361,6 @@ static bool i915_ttm_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); - struct ttm_resource *res = bo->resource; if (!obj) return false; @@ -378,45 +377,7 @@ static bool i915_ttm_eviction_valuable(struct ttm_buffer_object *bo, if (!i915_gem_object_evictable(obj)) return false; - switch (res->mem_type) { - case I915_PL_LMEM0: { - struct ttm_resource_manager *man = - ttm_manager_type(bo->bdev, res->mem_type); - struct i915_ttm_buddy_resource *bman_res = - to_ttm_buddy_resource(res); - struct drm_buddy *mm = bman_res->mm; - struct drm_buddy_block *block; - - if (!place->fpfn && !place->lpfn) - return true; - - GEM_BUG_ON(!place->lpfn); - - /* - * If we just want something mappable then we can quickly check - * if the current victim resource is using any of the CPU - * visible portion. - */ - if (!place->fpfn && - place->lpfn == i915_ttm_buddy_man_visible_size(man)) - return bman_res->used_visible_size > 0; - - /* Real range allocation */ - list_for_each_entry(block, &bman_res->blocks, link) { - unsigned long fpfn = - drm_buddy_block_offset(block) >> PAGE_SHIFT; - unsigned long lpfn = fpfn + - (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); - - if (place->fpfn < lpfn && place->lpfn > fpfn) - return true; - } - return false; - } default: - break; - } - - return true; + return ttm_bo_eviction_valuable(bo, place); } static void i915_ttm_evict_flags(struct ttm_buffer_object *bo, diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c index 427de1aaab36..e19452f0e100 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -173,6 +173,77 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man, kfree(bman_res); } +static bool i915_ttm_buddy_man_intersects(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + struct drm_buddy *mm = &bman->mm; + struct drm_buddy_block *block; + + if (!place->fpfn && !place->lpfn) + return true; + + GEM_BUG_ON(!place->lpfn); + + /* + * If we just want something mappable then we can quickly check + * if the current victim resource is using any of the CPU + * visible portion. + */ + if (!place->fpfn && + place->lpfn == i915_ttm_buddy_man_visible_size(man)) + return bman_res->used_visible_size > 0; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, &bman_res->blocks, link) { + unsigned long fpfn = + drm_buddy_block_offset(block) >> PAGE_SHIFT; + unsigned long lpfn = fpfn + + (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + + if (place->fpfn < lpfn && place->lpfn > fpfn) + return true; + } + + return false; +} + +static bool i915_ttm_buddy_man_compatible(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + struct drm_buddy *mm = &bman->mm; + struct drm_buddy_block *block; + + if (!place->fpfn && !place->lpfn) + return true; + + GEM_BUG_ON(!place->lpfn); + + if (!place->fpfn && + place->lpfn == i915_ttm_buddy_man_visible_size(man)) + return bman_res->used_visible_size == res->num_pages; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, &bman_res->blocks, link) { + unsigned long fpfn = + drm_buddy_block_offset(block) >> PAGE_SHIFT; + unsigned long lpfn = fpfn + + (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + + if (fpfn < place->fpfn || lpfn > place->lpfn) + return false; + } + + return true; +} + static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { @@ -200,6 +271,8 @@ static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = { .alloc = i915_ttm_buddy_man_alloc, .free = i915_ttm_buddy_man_free, + .intersects = i915_ttm_buddy_man_intersects, + .compatible = i915_ttm_buddy_man_compatible, .debug = i915_ttm_buddy_man_debug, }; From 73b984d8722e3ee077a8591b27d8c4d1a2d72020 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Sat, 20 Aug 2022 00:33:03 -0700 Subject: [PATCH 290/396] drm/nouveau: Implement intersect/compatible functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented a new intersect and compatible callback function fetching the start offset from struct ttm_resource. Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220820073304.178444-5-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/nouveau/nouveau_mem.c | 29 +++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_mem.h | 6 ++++++ drivers/gpu/drm/nouveau/nouveau_ttm.c | 24 ++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 2e517cdc24c9..76f8edefa637 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -187,3 +187,32 @@ nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp, *res = &mem->base; return 0; } + +bool +nouveau_mem_intersects(struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + u32 num_pages = PFN_UP(size); + + /* Don't evict BOs outside of the requested placement range */ + if (place->fpfn >= (res->start + num_pages) || + (place->lpfn && place->lpfn <= res->start)) + return false; + + return true; +} + +bool +nouveau_mem_compatible(struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + u32 num_pages = PFN_UP(size); + + if (res->start < place->fpfn || + (place->lpfn && (res->start + num_pages) > place->lpfn)) + return false; + + return true; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h index 325551eba5cd..1ee6cdb9ad9b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.h +++ b/drivers/gpu/drm/nouveau/nouveau_mem.h @@ -25,6 +25,12 @@ int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp, struct ttm_resource **); void nouveau_mem_del(struct ttm_resource_manager *man, struct ttm_resource *); +bool nouveau_mem_intersects(struct ttm_resource *res, + const struct ttm_place *place, + size_t size); +bool nouveau_mem_compatible(struct ttm_resource *res, + const struct ttm_place *place, + size_t size); int nouveau_mem_vram(struct ttm_resource *, bool contig, u8 page); int nouveau_mem_host(struct ttm_resource *, struct ttm_tt *); void nouveau_mem_fini(struct nouveau_mem *); diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 85f1f5a0fe5d..9602c30928f2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -42,6 +42,24 @@ nouveau_manager_del(struct ttm_resource_manager *man, nouveau_mem_del(man, reg); } +static bool +nouveau_manager_intersects(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + return nouveau_mem_intersects(res, place, size); +} + +static bool +nouveau_manager_compatible(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + return nouveau_mem_compatible(res, place, size); +} + static int nouveau_vram_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, @@ -73,6 +91,8 @@ nouveau_vram_manager_new(struct ttm_resource_manager *man, const struct ttm_resource_manager_func nouveau_vram_manager = { .alloc = nouveau_vram_manager_new, .free = nouveau_manager_del, + .intersects = nouveau_manager_intersects, + .compatible = nouveau_manager_compatible, }; static int @@ -97,6 +117,8 @@ nouveau_gart_manager_new(struct ttm_resource_manager *man, const struct ttm_resource_manager_func nouveau_gart_manager = { .alloc = nouveau_gart_manager_new, .free = nouveau_manager_del, + .intersects = nouveau_manager_intersects, + .compatible = nouveau_manager_compatible, }; static int @@ -130,6 +152,8 @@ nv04_gart_manager_new(struct ttm_resource_manager *man, const struct ttm_resource_manager_func nv04_gart_manager = { .alloc = nv04_gart_manager_new, .free = nouveau_manager_del, + .intersects = nouveau_manager_intersects, + .compatible = nouveau_manager_compatible, }; static int From 6d3c900c12d72667341bcff338c252e22728b942 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Date: Sat, 20 Aug 2022 00:33:04 -0700 Subject: [PATCH 291/396] drm/ttm: Switch to using the new res callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply new intersect and compatible callback instead of having a generic placement range verfications. v2: Added a separate callback for compatiblilty checks (Christian) v3: Cleanups and removal of workarounds Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220820073304.178444-6-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 47 ++++++++----------------- drivers/gpu/drm/ttm/ttm_resource.c | 17 ++------- 2 files changed, 16 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 170935c294f5..7d25a10395c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1328,11 +1328,12 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { - unsigned long num_pages = bo->resource->num_pages; struct dma_resv_iter resv_cursor; - struct amdgpu_res_cursor cursor; struct dma_fence *f; + if (!amdgpu_bo_is_amdgpu_bo(bo)) + return ttm_bo_eviction_valuable(bo, place); + /* Swapout? */ if (bo->resource->mem_type == TTM_PL_SYSTEM) return true; @@ -1351,39 +1352,19 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, return false; } - switch (bo->resource->mem_type) { - case AMDGPU_PL_PREEMPT: - /* Preemptible BOs don't own system resources managed by the - * driver (pages, VRAM, GART space). They point to resources - * owned by someone else (e.g. pageable memory in user mode - * or a DMABuf). They are used in a preemptible context so we - * can guarantee no deadlocks and good QoS in case of MMU - * notifiers or DMABuf move notifiers from the resource owner. - */ - return false; - case TTM_PL_TT: - if (amdgpu_bo_is_amdgpu_bo(bo) && - amdgpu_bo_encrypted(ttm_to_amdgpu_bo(bo))) - return false; - return true; - - case TTM_PL_VRAM: - /* Check each drm MM node individually */ - amdgpu_res_first(bo->resource, 0, (u64)num_pages << PAGE_SHIFT, - &cursor); - while (cursor.remaining) { - if (place->fpfn < PFN_DOWN(cursor.start + cursor.size) - && !(place->lpfn && - place->lpfn <= PFN_DOWN(cursor.start))) - return true; - - amdgpu_res_next(&cursor, cursor.size); - } + /* Preemptible BOs don't own system resources managed by the + * driver (pages, VRAM, GART space). They point to resources + * owned by someone else (e.g. pageable memory in user mode + * or a DMABuf). They are used in a preemptible context so we + * can guarantee no deadlocks and good QoS in case of MMU + * notifiers or DMABuf move notifiers from the resource owner. + */ + if (bo->resource->mem_type == AMDGPU_PL_PREEMPT) return false; - default: - break; - } + if (bo->resource->mem_type == TTM_PL_TT && + amdgpu_bo_encrypted(ttm_to_amdgpu_bo(bo))) + return false; return ttm_bo_eviction_valuable(bo, place); } diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 0d1f862a582b..a729c32a1e48 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -276,17 +276,9 @@ bool ttm_resource_intersects(struct ttm_device *bdev, if (!res) return false; - if (!place) - return true; - man = ttm_manager_type(bdev, res->mem_type); - if (!man->func->intersects) { - if (place->fpfn >= (res->start + res->num_pages) || - (place->lpfn && place->lpfn <= res->start)) - return false; - + if (!place || !man->func->intersects) return true; - } return man->func->intersects(man, res, place, size); } @@ -314,13 +306,8 @@ bool ttm_resource_compatible(struct ttm_device *bdev, return false; man = ttm_manager_type(bdev, res->mem_type); - if (!man->func->compatible) { - if (res->start < place->fpfn || - (place->lpfn && (res->start + res->num_pages) > place->lpfn)) - return false; - + if (!man->func->compatible) return true; - } return man->func->compatible(man, res, place, size); } From fcfd3e5fb2f052f6f466285107f449d462277a99 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Fri, 19 Aug 2022 16:08:49 +0200 Subject: [PATCH 292/396] drm/lcdif: Clean up headers Drop unneeded headers, sort rest alphabetically, no functional change. Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Liu Ying <victor.liu@nxp.com> Reported-by: Liu Ying <victor.liu@oss.nxp.com> Tested-by: Martyn Welch <martyn.welch@collabora.com> Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant") Signed-off-by: Marek Vasut <marex@denx.de> Cc: Alexander Stein <alexander.stein@ew.tq-group.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Liu Ying <victor.liu@nxp.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Marek Vasut <marex@denx.de> Cc: Martyn Welch <martyn.welch@collabora.com> Cc: Peng Fan <peng.fan@nxp.com> Cc: Robby Cai <robby.cai@nxp.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Stefan Agner <stefan@agner.ch> Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220819140852.255187-1-marex@denx.de --- drivers/gpu/drm/mxsfb/lcdif_drv.c | 3 --- drivers/gpu/drm/mxsfb/lcdif_drv.h | 1 + drivers/gpu/drm/mxsfb/lcdif_kms.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c index 05db135800db..4f16947212b6 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_drv.c +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c @@ -8,7 +8,6 @@ #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/io.h> -#include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -16,10 +15,8 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> -#include <drm/drm_connector.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_fourcc.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_mode_config.h> diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h b/drivers/gpu/drm/mxsfb/lcdif_drv.h index cb916341e845..6cdba6e20c02 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_drv.h +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h @@ -8,6 +8,7 @@ #ifndef __LCDIF_DRV_H__ #define __LCDIF_DRV_H__ +#include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> #include <drm/drm_encoder.h> diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index c7efc0d27f0e..750e7e7ea8e8 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -17,9 +17,9 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_encoder.h> -#include <drm/drm_framebuffer.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_plane.h> From 5e6723ef3fda07b4d586965af3c7af2a957480a2 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Fri, 19 Aug 2022 16:08:50 +0200 Subject: [PATCH 293/396] drm/lcdif: Consistently use plain timings Drop the crtc_ prefix from mode, consistently use the plain one. Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Liu Ying <victor.liu@nxp.com> Reported-by: Liu Ying <victor.liu@oss.nxp.com> Tested-by: Martyn Welch <martyn.welch@collabora.com> Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant") Signed-off-by: Marek Vasut <marex@denx.de> Cc: Alexander Stein <alexander.stein@ew.tq-group.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Liu Ying <victor.liu@nxp.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Marek Vasut <marex@denx.de> Cc: Martyn Welch <martyn.welch@collabora.com> Cc: Peng Fan <peng.fan@nxp.com> Cc: Robby Cai <robby.cai@nxp.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220819140852.255187-2-marex@denx.de --- drivers/gpu/drm/mxsfb/lcdif_kms.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index 750e7e7ea8e8..db7a90e5497c 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -122,8 +122,8 @@ static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags) writel(ctrl, lcdif->base + LCDC_V8_CTRL); - writel(DISP_SIZE_DELTA_Y(m->crtc_vdisplay) | - DISP_SIZE_DELTA_X(m->crtc_hdisplay), + writel(DISP_SIZE_DELTA_Y(m->vdisplay) | + DISP_SIZE_DELTA_X(m->hdisplay), lcdif->base + LCDC_V8_DISP_SIZE); writel(HSYN_PARA_BP_H(m->htotal - m->hsync_end) | @@ -138,8 +138,8 @@ static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags) VSYN_HSYN_WIDTH_PW_H(m->hsync_end - m->hsync_start), lcdif->base + LCDC_V8_VSYN_HSYN_WIDTH); - writel(CTRLDESCL0_1_HEIGHT(m->crtc_vdisplay) | - CTRLDESCL0_1_WIDTH(m->crtc_hdisplay), + writel(CTRLDESCL0_1_HEIGHT(m->vdisplay) | + CTRLDESCL0_1_WIDTH(m->hdisplay), lcdif->base + LCDC_V8_CTRLDESCL0_1); writel(CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb->pitches[0]), From 71c627c0a87acb13080317c5bae1f1423bebd5ef Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Fri, 19 Aug 2022 16:08:51 +0200 Subject: [PATCH 294/396] drm/lcdif: Clean up debug prints and comments Update debug print to report bridge timings over connector ones. Drop missed comment commit from mxsfb. Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Liu Ying <victor.liu@nxp.com> Reported-by: Liu Ying <victor.liu@oss.nxp.com> Tested-by: Martyn Welch <martyn.welch@collabora.com> Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant") Signed-off-by: Marek Vasut <marex@denx.de> Cc: Alexander Stein <alexander.stein@ew.tq-group.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Liu Ying <victor.liu@nxp.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Marek Vasut <marex@denx.de> Cc: Martyn Welch <martyn.welch@collabora.com> Cc: Peng Fan <peng.fan@nxp.com> Cc: Robby Cai <robby.cai@nxp.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220819140852.255187-3-marex@denx.de --- drivers/gpu/drm/mxsfb/lcdif_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index db7a90e5497c..b1092aab1423 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -203,7 +203,7 @@ static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif, DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n", m->crtc_clock, (int)(clk_get_rate(lcdif->clk) / 1000)); - DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n", + DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n", bus_flags); DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags); From 6e1853589ea627490f85435b9e81843129b08c10 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Fri, 19 Aug 2022 16:08:52 +0200 Subject: [PATCH 295/396] drm/lcdif: switch to devm_drm_of_get_bridge The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Liu Ying <victor.liu@nxp.com> Reported-by: Liu Ying <victor.liu@oss.nxp.com> Tested-by: Martyn Welch <martyn.welch@collabora.com> Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant") Signed-off-by: Marek Vasut <marex@denx.de> Cc: Alexander Stein <alexander.stein@ew.tq-group.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Liu Ying <victor.liu@nxp.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Marek Vasut <marex@denx.de> Cc: Martyn Welch <martyn.welch@collabora.com> Cc: Peng Fan <peng.fan@nxp.com> Cc: Robby Cai <robby.cai@nxp.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Stefan Agner <stefan@agner.ch> Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220819140852.255187-4-marex@denx.de --- drivers/gpu/drm/mxsfb/lcdif_drv.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c index 4f16947212b6..075002ed6fb0 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_drv.c +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c @@ -42,23 +42,11 @@ static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif) { struct drm_device *drm = lcdif->drm; struct drm_bridge *bridge; - struct drm_panel *panel; int ret; - ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, - &bridge); - if (ret) - return ret; - - if (panel) { - bridge = devm_drm_panel_bridge_add_typed(drm->dev, panel, - DRM_MODE_CONNECTOR_DPI); - if (IS_ERR(bridge)) - return PTR_ERR(bridge); - } - - if (!bridge) - return -ENODEV; + bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); ret = drm_bridge_attach(&lcdif->encoder, bridge, NULL, 0); if (ret) From ee50b00244086453dfb7076e4b80214948cd0507 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan+linaro@kernel.org> Date: Mon, 11 Jul 2022 09:52:02 +0200 Subject: [PATCH 296/396] drm/panel-edp: add AUO B133UAN02.1 panel entry Add an eDP panel entry for AUO B133UAN02.1. Due to lack of documentation, use the delay_200_500_e50 timings like some other AUO entries for now. Signed-off-by: Johan Hovold <johan+linaro@kernel.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220711075202.21775-1-johan+linaro@kernel.org --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index e6645d6e9b59..5263d11de952 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1877,6 +1877,7 @@ static const struct panel_delay delay_200_500_e200 = { */ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1e9b, &delay_200_500_e50, "B133UAN02.1"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"), From 008973fcbce429a2b0929108b6f9495d885bb1a3 Mon Sep 17 00:00:00 2001 From: Beniamin Sandu <beniaminsandu@gmail.com> Date: Mon, 15 Aug 2022 13:40:28 +0300 Subject: [PATCH 297/396] drm/nouveau/hwmon: use simplified HWMON_CHANNEL_INFO macro This makes the code look cleaner and easier to read. Signed-off-by: Beniamin Sandu <beniaminsandu@gmail.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220815104028.381271-1-beniaminsandu@gmail.com --- drivers/gpu/drm/nouveau/nouveau_hwmon.c | 85 +++++-------------------- 1 file changed, 17 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c index 1c3104d20571..a7db7c31064b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c +++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c @@ -211,75 +211,24 @@ static const struct attribute_group temp1_auto_point_sensor_group = { #define N_ATTR_GROUPS 3 -static const u32 nouveau_config_chip[] = { - HWMON_C_UPDATE_INTERVAL, - 0 -}; - -static const u32 nouveau_config_in[] = { - HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_LABEL, - 0 -}; - -static const u32 nouveau_config_temp[] = { - HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | - HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_EMERGENCY | - HWMON_T_EMERGENCY_HYST, - 0 -}; - -static const u32 nouveau_config_fan[] = { - HWMON_F_INPUT, - 0 -}; - -static const u32 nouveau_config_pwm[] = { - HWMON_PWM_INPUT | HWMON_PWM_ENABLE, - 0 -}; - -static const u32 nouveau_config_power[] = { - HWMON_P_INPUT | HWMON_P_CAP_MAX | HWMON_P_CRIT, - 0 -}; - -static const struct hwmon_channel_info nouveau_chip = { - .type = hwmon_chip, - .config = nouveau_config_chip, -}; - -static const struct hwmon_channel_info nouveau_temp = { - .type = hwmon_temp, - .config = nouveau_config_temp, -}; - -static const struct hwmon_channel_info nouveau_fan = { - .type = hwmon_fan, - .config = nouveau_config_fan, -}; - -static const struct hwmon_channel_info nouveau_in = { - .type = hwmon_in, - .config = nouveau_config_in, -}; - -static const struct hwmon_channel_info nouveau_pwm = { - .type = hwmon_pwm, - .config = nouveau_config_pwm, -}; - -static const struct hwmon_channel_info nouveau_power = { - .type = hwmon_power, - .config = nouveau_config_power, -}; - static const struct hwmon_channel_info *nouveau_info[] = { - &nouveau_chip, - &nouveau_temp, - &nouveau_fan, - &nouveau_in, - &nouveau_pwm, - &nouveau_power, + HWMON_CHANNEL_INFO(chip, + HWMON_C_UPDATE_INTERVAL), + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | + HWMON_T_MAX | HWMON_T_MAX_HYST | + HWMON_T_CRIT | HWMON_T_CRIT_HYST | + HWMON_T_EMERGENCY | HWMON_T_EMERGENCY_HYST), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT), + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | + HWMON_I_MIN | HWMON_I_MAX | + HWMON_I_LABEL), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE), + HWMON_CHANNEL_INFO(power, + HWMON_P_INPUT | HWMON_P_CAP_MAX | HWMON_P_CRIT), NULL }; From 83ebec7e0b4c2847d9cff2bcf1324cfc5287dfcb Mon Sep 17 00:00:00 2001 From: wangjianli <wangjianli@cdjrlc.com> Date: Sun, 21 Aug 2022 22:30:38 +0800 Subject: [PATCH 298/396] subdev/clk: fix repeated words in comments Delete the redundant word 'at'. Signed-off-by: wangjianli <wangjianli@cdjrlc.com> Reviewed-by: Karol Herbst <kherbst@redhat.com> Signed-off-by: Karol Herbst <kherbst@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220821143038.46589-1-wangjianli@cdjrlc.com --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c index a139dafffe06..7c33542f651b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c @@ -581,7 +581,7 @@ gm20b_clk_prog(struct nvkm_clk *base) /* * Interim step for changing DVFS detection settings: low enough - * frequency to be safe at at DVFS coeff = 0. + * frequency to be safe at DVFS coeff = 0. * * 1. If voltage is increasing: * - safe frequency target matches the lowest - old - frequency From 0f9fa5f58c78426a93983a2cc0127fd98b020403 Mon Sep 17 00:00:00 2001 From: Steev Klimaszewski <steev@kali.org> Date: Wed, 20 Jul 2022 00:41:52 -0500 Subject: [PATCH 299/396] drm/panel-edp: add IVO M133NW4J-R3 panel entry Add an eDP panel entry for IVO M133NW4J-R3. Due to lack of documentation, use the delay_200_500_p2e100 timings for now. Signed-off-by: Steev Klimaszewski <steev@kali.org> [dianders: fixed typo in commit message] Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720054152.2450-1-steev@kali.org --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 5263d11de952..a95db0cfa43c 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1891,6 +1891,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"), EDP_PANEL_ENTRY('I', 'V', 'O', 0x057d, &delay_200_500_e200, "R140NWF5 RH"), + EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "M133NW4J-R3"), EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"), EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"), From 8c5e9bbb3662b09fb9b5353dc48d2f871f13127f Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:30 -0400 Subject: [PATCH 300/396] drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table) Just to make this more clear to outside contributors that these are DC-specific structs, as this also threw me into a loop a number of times before I figured out the purpose of this. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-2-lyude@redhat.com --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 9 ++++----- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +++++----- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 4 ++-- .../gpu/drm/amd/display/include/link_service_types.h | 11 ++++++++--- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index d66e3cd64ebd..b2e7e1630a4b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -153,9 +153,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps( return result; } -static void get_payload_table( - struct amdgpu_dm_connector *aconnector, - struct dp_mst_stream_allocation_table *proposed_table) +static void get_payload_table(struct amdgpu_dm_connector *aconnector, + struct dc_dp_mst_stream_allocation_table *proposed_table) { int i; struct drm_dp_mst_topology_mgr *mst_mgr = @@ -177,7 +176,7 @@ static void get_payload_table( mst_mgr->payloads[i].payload_state == DP_PAYLOAD_REMOTE) { - struct dp_mst_stream_allocation *sa = + struct dc_dp_mst_stream_allocation *sa = &proposed_table->stream_allocations[ proposed_table->stream_count]; @@ -201,7 +200,7 @@ void dm_helpers_dp_update_branch_info( bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, const struct dc_stream_state *stream, - struct dp_mst_stream_allocation_table *proposed_table, + struct dc_dp_mst_stream_allocation_table *proposed_table, bool enable) { struct amdgpu_dm_connector *aconnector; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 9e51338441d0..e01424fb02ba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3516,7 +3516,7 @@ static void update_mst_stream_alloc_table( struct dc_link *link, struct stream_encoder *stream_enc, struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc? - const struct dp_mst_stream_allocation_table *proposed_table) + const struct dc_dp_mst_stream_allocation_table *proposed_table) { struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 }; struct link_mst_stream_allocation *dc_alloc; @@ -3679,7 +3679,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; @@ -3784,7 +3784,7 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); @@ -3873,7 +3873,7 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); @@ -3957,7 +3957,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); int i; bool mst_mode = (link->type == dc_connection_mst_branch); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index fb6a2d7b6470..8173f4b80424 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -33,7 +33,7 @@ #include "dc_types.h" #include "dc.h" -struct dp_mst_stream_allocation_table; +struct dc_dp_mst_stream_allocation_table; struct aux_payload; enum aux_return_code_type; @@ -77,7 +77,7 @@ void dm_helpers_dp_update_branch_info( bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, const struct dc_stream_state *stream, - struct dp_mst_stream_allocation_table *proposed_table, + struct dc_dp_mst_stream_allocation_table *proposed_table, bool enable); /* diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 79fabc51c991..f75ed6f8fcb8 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -246,8 +246,13 @@ union dpcd_training_lane_set { }; +/* AMD's copy of various payload data for MST. We have two copies of the payload table (one in DRM, + * one in DC) since DRM's MST helpers can't be accessed here. This stream allocation table should + * _ONLY_ be filled out from DM and then passed to DC, do NOT use these for _any_ kind of atomic + * state calculations in DM, or you will break something. + */ /* DP MST stream allocation (payload bandwidth number) */ -struct dp_mst_stream_allocation { +struct dc_dp_mst_stream_allocation { uint8_t vcp_id; /* number of slots required for the DP stream in * transport packet */ @@ -255,11 +260,11 @@ struct dp_mst_stream_allocation { }; /* DP MST stream allocation table */ -struct dp_mst_stream_allocation_table { +struct dc_dp_mst_stream_allocation_table { /* number of DP video streams */ int stream_count; /* array of stream allocations */ - struct dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; + struct dc_dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; }; #endif /*__DAL_LINK_SERVICE_TYPES_H__*/ From dbaadb3cebaad49c37e3fec937e73e6e41054404 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:31 -0400 Subject: [PATCH 301/396] drm/amdgpu/dm/mst: Rename get_payload_table() This function isn't too confusing if you see the comment around the call-site for it, but if you don't then it's not at all obvious this is meant to copy DRM's payload table over to DC's internal state structs. Seeing this function before finding that comment definitely threw me into a loop a few times. So, let's rename this to make it's purpose more obvious regardless of where in the code you are. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-3-lyude@redhat.com --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index b2e7e1630a4b..0177a275b4df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -153,8 +153,9 @@ enum dc_edid_status dm_helpers_parse_edid_caps( return result; } -static void get_payload_table(struct amdgpu_dm_connector *aconnector, - struct dc_dp_mst_stream_allocation_table *proposed_table) +static void +fill_dc_mst_payload_table_from_drm(struct amdgpu_dm_connector *aconnector, + struct dc_dp_mst_stream_allocation_table *proposed_table) { int i; struct drm_dp_mst_topology_mgr *mst_mgr = @@ -252,7 +253,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( * stream. AMD ASIC stream slot allocation should follow the same * sequence. copy DRM MST allocation to dc */ - get_payload_table(aconnector, proposed_table); + fill_dc_mst_payload_table_from_drm(aconnector, proposed_table); return true; } From 48b6b3726fb7c189410959d2b8915c209fbf9e7c Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:32 -0400 Subject: [PATCH 302/396] drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In retrospect, the name I chose for this originally is confusing, as there's a lot more info in here then just the VCPI. This really should be called a payload. Let's make it more obvious that this is meant to be related to the atomic state and is about payloads by renaming it to drm_dp_mst_atomic_payload. Also, rename various variables throughout the code that use atomic payloads. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-4-lyude@redhat.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 96 +++++++++---------- include/drm/display/drm_dp_mst_helper.h | 4 +- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 7a94a5288e8d..f448e3e5ec6e 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4370,7 +4370,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, int pbn_div) { struct drm_dp_mst_topology_state *topology_state; - struct drm_dp_vcpi_allocation *pos, *vcpi = NULL; + struct drm_dp_mst_atomic_payload *pos, *payload = NULL; int prev_slots, prev_bw, req_slots; topology_state = drm_atomic_get_mst_topology_state(state, mgr); @@ -4378,11 +4378,11 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, return PTR_ERR(topology_state); /* Find the current allocation for this port, if any */ - list_for_each_entry(pos, &topology_state->vcpis, next) { + list_for_each_entry(pos, &topology_state->payloads, next) { if (pos->port == port) { - vcpi = pos; - prev_slots = vcpi->vcpi; - prev_bw = vcpi->pbn; + payload = pos; + prev_slots = payload->vcpi; + prev_bw = payload->pbn; /* * This should never happen, unless the driver tries @@ -4399,7 +4399,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, break; } } - if (!vcpi) { + if (!payload) { prev_slots = 0; prev_bw = 0; } @@ -4417,17 +4417,17 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, port, prev_bw, pbn); /* Add the new allocation to the state */ - if (!vcpi) { - vcpi = kzalloc(sizeof(*vcpi), GFP_KERNEL); - if (!vcpi) + if (!payload) { + payload = kzalloc(sizeof(*payload), GFP_KERNEL); + if (!payload) return -ENOMEM; drm_dp_mst_get_port_malloc(port); - vcpi->port = port; - list_add(&vcpi->next, &topology_state->vcpis); + payload->port = port; + list_add(&payload->next, &topology_state->payloads); } - vcpi->vcpi = req_slots; - vcpi->pbn = pbn; + payload->vcpi = req_slots; + payload->pbn = pbn; return req_slots; } @@ -4464,21 +4464,21 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_port *port) { struct drm_dp_mst_topology_state *topology_state; - struct drm_dp_vcpi_allocation *pos; + struct drm_dp_mst_atomic_payload *pos; bool found = false; topology_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(topology_state)) return PTR_ERR(topology_state); - list_for_each_entry(pos, &topology_state->vcpis, next) { + list_for_each_entry(pos, &topology_state->payloads, next) { if (pos->port == port) { found = true; break; } } if (WARN_ON(!found)) { - drm_err(mgr->dev, "no VCPI for [MST PORT:%p] found in mst state %p\n", + drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst state %p\n", port, &topology_state->base); return -EINVAL; } @@ -5060,7 +5060,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj) { struct drm_dp_mst_topology_state *state, *old_state = to_dp_mst_topology_state(obj->state); - struct drm_dp_vcpi_allocation *pos, *vcpi; + struct drm_dp_mst_atomic_payload *pos, *payload; state = kmemdup(old_state, sizeof(*state), GFP_KERNEL); if (!state) @@ -5068,25 +5068,25 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj) __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); - INIT_LIST_HEAD(&state->vcpis); + INIT_LIST_HEAD(&state->payloads); - list_for_each_entry(pos, &old_state->vcpis, next) { + list_for_each_entry(pos, &old_state->payloads, next) { /* Prune leftover freed VCPI allocations */ if (!pos->vcpi) continue; - vcpi = kmemdup(pos, sizeof(*vcpi), GFP_KERNEL); - if (!vcpi) + payload = kmemdup(pos, sizeof(*payload), GFP_KERNEL); + if (!payload) goto fail; - drm_dp_mst_get_port_malloc(vcpi->port); - list_add(&vcpi->next, &state->vcpis); + drm_dp_mst_get_port_malloc(payload->port); + list_add(&payload->next, &state->payloads); } return &state->base; fail: - list_for_each_entry_safe(pos, vcpi, &state->vcpis, next) { + list_for_each_entry_safe(pos, payload, &state->payloads, next) { drm_dp_mst_put_port_malloc(pos->port); kfree(pos); } @@ -5100,9 +5100,9 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, { struct drm_dp_mst_topology_state *mst_state = to_dp_mst_topology_state(state); - struct drm_dp_vcpi_allocation *pos, *tmp; + struct drm_dp_mst_atomic_payload *pos, *tmp; - list_for_each_entry_safe(pos, tmp, &mst_state->vcpis, next) { + list_for_each_entry_safe(pos, tmp, &mst_state->payloads, next) { /* We only keep references to ports with non-zero VCPIs */ if (pos->vcpi) drm_dp_mst_put_port_malloc(pos->port); @@ -5135,7 +5135,7 @@ static int drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_topology_state *state) { - struct drm_dp_vcpi_allocation *vcpi; + struct drm_dp_mst_atomic_payload *payload; struct drm_dp_mst_port *port; int pbn_used = 0, ret; bool found = false; @@ -5143,9 +5143,9 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb, /* Check that we have at least one port in our state that's downstream * of this branch, otherwise we can skip this branch */ - list_for_each_entry(vcpi, &state->vcpis, next) { - if (!vcpi->pbn || - !drm_dp_mst_port_downstream_of_branch(vcpi->port, mstb)) + list_for_each_entry(payload, &state->payloads, next) { + if (!payload->pbn || + !drm_dp_mst_port_downstream_of_branch(payload->port, mstb)) continue; found = true; @@ -5176,7 +5176,7 @@ static int drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port, struct drm_dp_mst_topology_state *state) { - struct drm_dp_vcpi_allocation *vcpi; + struct drm_dp_mst_atomic_payload *payload; int pbn_used = 0; if (port->pdt == DP_PEER_DEVICE_NONE) @@ -5185,10 +5185,10 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port, if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) { bool found = false; - list_for_each_entry(vcpi, &state->vcpis, next) { - if (vcpi->port != port) + list_for_each_entry(payload, &state->payloads, next) { + if (payload->port != port) continue; - if (!vcpi->pbn) + if (!payload->pbn) return 0; found = true; @@ -5208,7 +5208,7 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port, return -EINVAL; } - pbn_used = vcpi->pbn; + pbn_used = payload->pbn; } else { pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit(port->mstb, state); @@ -5233,25 +5233,25 @@ static inline int drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_topology_state *mst_state) { - struct drm_dp_vcpi_allocation *vcpi; + struct drm_dp_mst_atomic_payload *payload; int avail_slots = mst_state->total_avail_slots, payload_count = 0; - list_for_each_entry(vcpi, &mst_state->vcpis, next) { - /* Releasing VCPI is always OK-even if the port is gone */ - if (!vcpi->vcpi) { + list_for_each_entry(payload, &mst_state->payloads, next) { + /* Releasing payloads is always OK-even if the port is gone */ + if (!payload->vcpi) { drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all VCPI slots\n", - vcpi->port); + payload->port); continue; } drm_dbg_atomic(mgr->dev, "[MST PORT:%p] requires %d vcpi slots\n", - vcpi->port, vcpi->vcpi); + payload->port, payload->vcpi); - avail_slots -= vcpi->vcpi; + avail_slots -= payload->vcpi; if (avail_slots < 0) { drm_dbg_atomic(mgr->dev, "[MST PORT:%p] not enough VCPI slots in mst state %p (avail=%d)\n", - vcpi->port, mst_state, avail_slots + vcpi->vcpi); + payload->port, mst_state, avail_slots + payload->vcpi); return -ENOSPC; } @@ -5284,7 +5284,7 @@ drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr, int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr) { struct drm_dp_mst_topology_state *mst_state; - struct drm_dp_vcpi_allocation *pos; + struct drm_dp_mst_atomic_payload *pos; struct drm_connector *connector; struct drm_connector_state *conn_state; struct drm_crtc *crtc; @@ -5295,7 +5295,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm if (IS_ERR(mst_state)) return -EINVAL; - list_for_each_entry(pos, &mst_state->vcpis, next) { + list_for_each_entry(pos, &mst_state->payloads, next) { connector = pos->port->connector; @@ -5349,7 +5349,7 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, bool enable) { struct drm_dp_mst_topology_state *mst_state; - struct drm_dp_vcpi_allocation *pos; + struct drm_dp_mst_atomic_payload *pos; bool found = false; int vcpi = 0; @@ -5358,7 +5358,7 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, if (IS_ERR(mst_state)) return PTR_ERR(mst_state); - list_for_each_entry(pos, &mst_state->vcpis, next) { + list_for_each_entry(pos, &mst_state->payloads, next) { if (pos->port == port) { found = true; break; @@ -5544,7 +5544,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, mst_state->start_slot = 1; mst_state->mgr = mgr; - INIT_LIST_HEAD(&mst_state->vcpis); + INIT_LIST_HEAD(&mst_state->payloads); drm_atomic_private_obj_init(dev, &mgr->base, &mst_state->base, diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 10adec068b7f..5671173f9f37 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -542,7 +542,7 @@ struct drm_dp_payload { #define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base) -struct drm_dp_vcpi_allocation { +struct drm_dp_mst_atomic_payload { struct drm_dp_mst_port *port; int vcpi; int pbn; @@ -552,7 +552,7 @@ struct drm_dp_vcpi_allocation { struct drm_dp_mst_topology_state { struct drm_private_state base; - struct list_head vcpis; + struct list_head payloads; struct drm_dp_mst_topology_mgr *mgr; u8 total_avail_slots; u8 start_slot; From df78f7f660cdd5974b68649a95dbb34da4d4dfa7 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:33 -0400 Subject: [PATCH 303/396] drm/display/dp_mst: Call them time slots, not VCPI slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VCPI is only sort of the correct term here, originally the majority of this code simply referred to timeslots vaguely as "slots" - and since I started working on it and adding atomic functionality, the name "VCPI slots" has been used to represent time slots. Now that we actually have consistent access to the DisplayPort spec thanks to VESA, I now know this isn't actually the proper term - as the specification refers to these as time slots. Since we're trying to make this code as easy to figure out as possible, let's take this opportunity to correct this nomenclature and call them by their proper name - timeslots. Likewise, we rename various functions appropriately, along with replacing references in the kernel documentation and various debugging messages. It's important to note that this patch series leaves the legacy MST code untouched for the most part, which is fine since we'll be removing it soon anyhow. There should be no functional changes in this series. v2: * Add note that Wayne Lin from AMD suggested regarding slots being between the source DP Tx and the immediate downstream DP Rx Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-5-lyude@redhat.com --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 28 ++--- drivers/gpu/drm/display/drm_dp_mst_topology.c | 106 +++++++++--------- drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 +- include/drm/display/drm_dp_mst_helper.h | 12 +- 6 files changed, 81 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 85fdd6baf803..cd30b02af8ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6401,7 +6401,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, clock = adjusted_mode->clock; dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false); } - dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_vcpi_slots(state, + dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port, dm_new_connector_state->pbn, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 2e74ccf7df5b..655d63b20b33 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -472,7 +472,7 @@ static int dm_dp_mst_atomic_check(struct drm_connector *connector, return 0; } - return drm_dp_atomic_release_vcpi_slots(state, + return drm_dp_atomic_release_time_slots(state, mst_mgr, mst_port); } @@ -785,7 +785,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, if (initial_slack[next_index] > fair_pbn_alloc) { vars[next_index].pbn += fair_pbn_alloc; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, @@ -795,7 +795,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn); } else { vars[next_index].pbn -= fair_pbn_alloc; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, @@ -804,7 +804,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, } } else { vars[next_index].pbn += initial_slack[next_index]; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, @@ -814,7 +814,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16; } else { vars[next_index].pbn -= initial_slack[next_index]; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, @@ -872,7 +872,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state, break; vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps); - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, @@ -884,7 +884,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state, vars[next_index].bpp_x16 = 0; } else { vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps); - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, @@ -971,11 +971,11 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; - if (drm_dp_atomic_find_vcpi_slots(state, - params[i].port->mgr, - params[i].port, - vars[i + k].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + if (drm_dp_atomic_find_time_slots(state, + params[i].port->mgr, + params[i].port, + vars[i + k].pbn, + dm_mst_get_pbn_divider(dc_link)) < 0) return false; } if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) { @@ -989,7 +989,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps); vars[i + k].dsc_enabled = true; vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, vars[i + k].pbn, @@ -999,7 +999,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, vars[i + k].pbn, diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index f448e3e5ec6e..fad80ab2b9db 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4293,11 +4293,11 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ EXPORT_SYMBOL(drm_dp_mst_get_edid); /** - * drm_dp_find_vcpi_slots() - Find VCPI slots for this PBN value + * drm_dp_find_vcpi_slots() - Find time slots for this PBN value * @mgr: manager to use * @pbn: payload bandwidth to convert into slots. * - * Calculate the number of VCPI slots that will be required for the given PBN + * Calculate the number of time slots that will be required for the given PBN * value. This function is deprecated, and should not be used in atomic * drivers. * @@ -4334,17 +4334,17 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, } /** - * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state + * drm_dp_atomic_find_time_slots() - Find and add time slots to the state * @state: global atomic state * @mgr: MST topology manager for the port - * @port: port to find vcpi slots for + * @port: port to find time slots for * @pbn: bandwidth required for the mode in PBN * @pbn_div: divider for DSC mode that takes FEC into account * - * Allocates VCPI slots to @port, replacing any previous VCPI allocations it + * Allocates time slots to @port, replacing any previous timeslot allocations it * may have had. Any atomic drivers which support MST must call this function * in their &drm_encoder_helper_funcs.atomic_check() callback to change the - * current VCPI allocation for the new state, but only when + * current timeslot allocation for the new state, but only when * &drm_crtc_state.mode_changed or &drm_crtc_state.connectors_changed is set * to ensure compatibility with userspace applications that still use the * legacy modesetting UAPI. @@ -4354,17 +4354,17 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, * * Additionally, it is OK to call this function multiple times on the same * @port as needed. It is not OK however, to call this function and - * drm_dp_atomic_release_vcpi_slots() in the same atomic check phase. + * drm_dp_atomic_release_time_slots() in the same atomic check phase. * * See also: - * drm_dp_atomic_release_vcpi_slots() + * drm_dp_atomic_release_time_slots() * drm_dp_mst_atomic_check() * * Returns: * Total slots in the atomic state assigned for this port, or a negative error * code if the port no longer exists */ -int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, +int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int pbn_div) @@ -4381,17 +4381,17 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, list_for_each_entry(pos, &topology_state->payloads, next) { if (pos->port == port) { payload = pos; - prev_slots = payload->vcpi; + prev_slots = payload->time_slots; prev_bw = payload->pbn; /* * This should never happen, unless the driver tries - * releasing and allocating the same VCPI allocation, + * releasing and allocating the same timeslot allocation, * which is an error */ if (WARN_ON(!prev_slots)) { drm_err(mgr->dev, - "cannot allocate and release VCPI on [MST PORT:%p] in the same state\n", + "cannot allocate and release time slots on [MST PORT:%p] in the same state\n", port); return -EINVAL; } @@ -4409,7 +4409,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, req_slots = DIV_ROUND_UP(pbn, pbn_div); - drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] VCPI %d -> %d\n", + drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] TU %d -> %d\n", port->connector->base.id, port->connector->name, port, prev_slots, req_slots); drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] PBN %d -> %d\n", @@ -4426,20 +4426,20 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, payload->port = port; list_add(&payload->next, &topology_state->payloads); } - payload->vcpi = req_slots; + payload->time_slots = req_slots; payload->pbn = pbn; return req_slots; } -EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots); +EXPORT_SYMBOL(drm_dp_atomic_find_time_slots); /** - * drm_dp_atomic_release_vcpi_slots() - Release allocated vcpi slots + * drm_dp_atomic_release_time_slots() - Release allocated time slots * @state: global atomic state * @mgr: MST topology manager for the port - * @port: The port to release the VCPI slots from + * @port: The port to release the time slots from * - * Releases any VCPI slots that have been allocated to a port in the atomic + * Releases any time slots that have been allocated to a port in the atomic * state. Any atomic drivers which support MST must call this function in * their &drm_connector_helper_funcs.atomic_check() callback when the * connector will no longer have VCPI allocated (e.g. because its CRTC was @@ -4448,18 +4448,18 @@ EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots); * It is OK to call this even if @port has been removed from the system. * Additionally, it is OK to call this function multiple times on the same * @port as needed. It is not OK however, to call this function and - * drm_dp_atomic_find_vcpi_slots() on the same @port in a single atomic check + * drm_dp_atomic_find_time_slots() on the same @port in a single atomic check * phase. * * See also: - * drm_dp_atomic_find_vcpi_slots() + * drm_dp_atomic_find_time_slots() * drm_dp_mst_atomic_check() * * Returns: * 0 if all slots for this port were added back to * &drm_dp_mst_topology_state.avail_slots or negative error code */ -int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, +int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) { @@ -4483,16 +4483,16 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, return -EINVAL; } - drm_dbg_atomic(mgr->dev, "[MST PORT:%p] VCPI %d -> 0\n", port, pos->vcpi); - if (pos->vcpi) { + drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, pos->time_slots); + if (pos->time_slots) { drm_dp_mst_put_port_malloc(port); - pos->vcpi = 0; + pos->time_slots = 0; pos->pbn = 0; } return 0; } -EXPORT_SYMBOL(drm_dp_atomic_release_vcpi_slots); +EXPORT_SYMBOL(drm_dp_atomic_release_time_slots); /** * drm_dp_mst_update_slots() - updates the slot info depending on the DP ecoding format @@ -4546,7 +4546,7 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots); if (ret) { - drm_dbg_kms(mgr->dev, "failed to init vcpi slots=%d ret=%d\n", + drm_dbg_kms(mgr->dev, "failed to init time slots=%d ret=%d\n", DIV_ROUND_UP(pbn, mgr->pbn_div), ret); drm_dp_mst_topology_put_port(port); goto out; @@ -5071,8 +5071,8 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj) INIT_LIST_HEAD(&state->payloads); list_for_each_entry(pos, &old_state->payloads, next) { - /* Prune leftover freed VCPI allocations */ - if (!pos->vcpi) + /* Prune leftover freed timeslot allocations */ + if (!pos->time_slots) continue; payload = kmemdup(pos, sizeof(*payload), GFP_KERNEL); @@ -5104,7 +5104,7 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, list_for_each_entry_safe(pos, tmp, &mst_state->payloads, next) { /* We only keep references to ports with non-zero VCPIs */ - if (pos->vcpi) + if (pos->time_slots) drm_dp_mst_put_port_malloc(pos->port); kfree(pos); } @@ -5230,28 +5230,28 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port, } static inline int -drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_topology_state *mst_state) +drm_dp_mst_atomic_check_payload_alloc_limits(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state) { struct drm_dp_mst_atomic_payload *payload; int avail_slots = mst_state->total_avail_slots, payload_count = 0; list_for_each_entry(payload, &mst_state->payloads, next) { /* Releasing payloads is always OK-even if the port is gone */ - if (!payload->vcpi) { - drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all VCPI slots\n", + if (!payload->time_slots) { + drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all time slots\n", payload->port); continue; } - drm_dbg_atomic(mgr->dev, "[MST PORT:%p] requires %d vcpi slots\n", - payload->port, payload->vcpi); + drm_dbg_atomic(mgr->dev, "[MST PORT:%p] requires %d time slots\n", + payload->port, payload->time_slots); - avail_slots -= payload->vcpi; + avail_slots -= payload->time_slots; if (avail_slots < 0) { drm_dbg_atomic(mgr->dev, - "[MST PORT:%p] not enough VCPI slots in mst state %p (avail=%d)\n", - payload->port, mst_state, avail_slots + payload->vcpi); + "[MST PORT:%p] not enough time slots in mst state %p (avail=%d)\n", + payload->port, mst_state, avail_slots + payload->time_slots); return -ENOSPC; } @@ -5262,7 +5262,7 @@ drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr, return -EINVAL; } } - drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p VCPI avail=%d used=%d\n", + drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU avail=%d used=%d\n", mgr, mst_state, avail_slots, mst_state->total_avail_slots - avail_slots); return 0; @@ -5351,7 +5351,7 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, struct drm_dp_mst_topology_state *mst_state; struct drm_dp_mst_atomic_payload *pos; bool found = false; - int vcpi = 0; + int time_slots = 0; mst_state = drm_atomic_get_mst_topology_state(state, port->mgr); @@ -5367,30 +5367,30 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, if (!found) { drm_dbg_atomic(state->dev, - "[MST PORT:%p] Couldn't find VCPI allocation in mst state %p\n", + "[MST PORT:%p] Couldn't find payload in mst state %p\n", port, mst_state); return -EINVAL; } if (pos->dsc_enabled == enable) { drm_dbg_atomic(state->dev, - "[MST PORT:%p] DSC flag is already set to %d, returning %d VCPI slots\n", - port, enable, pos->vcpi); - vcpi = pos->vcpi; + "[MST PORT:%p] DSC flag is already set to %d, returning %d time slots\n", + port, enable, pos->time_slots); + time_slots = pos->time_slots; } if (enable) { - vcpi = drm_dp_atomic_find_vcpi_slots(state, port->mgr, port, pbn, pbn_div); + time_slots = drm_dp_atomic_find_time_slots(state, port->mgr, port, pbn, pbn_div); drm_dbg_atomic(state->dev, - "[MST PORT:%p] Enabling DSC flag, reallocating %d VCPI slots on the port\n", - port, vcpi); - if (vcpi < 0) + "[MST PORT:%p] Enabling DSC flag, reallocating %d time slots on the port\n", + port, time_slots); + if (time_slots < 0) return -EINVAL; } pos->dsc_enabled = enable; - return vcpi; + return time_slots; } EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc); /** @@ -5400,15 +5400,15 @@ EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc); * * Checks the given topology state for an atomic update to ensure that it's * valid. This includes checking whether there's enough bandwidth to support - * the new VCPI allocations in the atomic update. + * the new timeslot allocations in the atomic update. * * Any atomic drivers supporting DP MST must make sure to call this after * checking the rest of their state in their * &drm_mode_config_funcs.atomic_check() callback. * * See also: - * drm_dp_atomic_find_vcpi_slots() - * drm_dp_atomic_release_vcpi_slots() + * drm_dp_atomic_find_time_slots() + * drm_dp_atomic_release_time_slots() * * Returns: * @@ -5424,7 +5424,7 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state) if (!mgr->mst_state) continue; - ret = drm_dp_mst_atomic_check_vcpi_alloc_limit(mgr, mst_state); + ret = drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state); if (ret) break; diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 14d2a64193b2..1cebbc51d8fa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -70,7 +70,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, crtc_state->pipe_bpp, false); - slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, + slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, connector->port, crtc_state->pbn, drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr, @@ -344,8 +344,7 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, } mgr = &enc_to_mst(to_intel_encoder(old_conn_state->best_encoder))->primary->dp.mst_mgr; - ret = drm_dp_atomic_release_vcpi_slots(&state->base, mgr, - intel_connector->port); + ret = drm_dp_atomic_release_time_slots(&state->base, mgr, intel_connector->port); return ret; } diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index c8fedd7d227f..1d54f2cd38b2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1065,7 +1065,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, false); } - slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port, + slots = drm_dp_atomic_find_time_slots(state, &mstm->mgr, mstc->port, asyh->dp.pbn, 0); if (slots < 0) return slots; @@ -1277,7 +1277,7 @@ nv50_mstc_atomic_check(struct drm_connector *connector, return 0; } - return drm_dp_atomic_release_vcpi_slots(state, mgr, mstc->port); + return drm_dp_atomic_release_time_slots(state, mgr, mstc->port); } static int diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 5671173f9f37..9cdd2def56a1 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -544,7 +544,13 @@ struct drm_dp_payload { struct drm_dp_mst_atomic_payload { struct drm_dp_mst_port *port; - int vcpi; + + /** + * @time_slots: + * The number of timeslots allocated to this payload from the source DP Tx to + * the immediate downstream DP Rx + */ + int time_slots; int pbn; bool dsc_enabled; struct list_head next; @@ -846,7 +852,7 @@ void drm_dp_mst_connector_early_unregister(struct drm_connector *connector, struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr); int __must_check -drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, +drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int pbn_div); @@ -858,7 +864,7 @@ int __must_check drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr); int __must_check -drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, +drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, From 946c701407c33867573767db7a23e2b6696b5d9b Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:34 -0400 Subject: [PATCH 304/396] drm/display/dp_mst: Fix confusing docs for drm_dp_atomic_release_time_slots() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason we mention returning 0 if "slots have been added back to drm_dp_mst_topology_state->avail_slots". This is totally misleading, avail_slots is simply for figuring out the total number of slots available in total on the topology and has no relation to the current payload allocations. So, let's get rid of that comment. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-6-lyude@redhat.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index fad80ab2b9db..8a2ddfde594a 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4456,8 +4456,7 @@ EXPORT_SYMBOL(drm_dp_atomic_find_time_slots); * drm_dp_mst_atomic_check() * * Returns: - * 0 if all slots for this port were added back to - * &drm_dp_mst_topology_state.avail_slots or negative error code + * 0 on success, negative error code otherwise */ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, From 0bee2ae29eb4bdeaf5fb80b4ef48877bc448485a Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:35 -0400 Subject: [PATCH 305/396] drm/display/dp_mst: Add some missing kdocs for atomic MST structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we're about to start adding some stuff here, we may as well fill in any missing documentation that we forgot to write. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-7-lyude@redhat.com --- include/drm/display/drm_dp_mst_helper.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 9cdd2def56a1..3b155ad3eee4 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -542,7 +542,14 @@ struct drm_dp_payload { #define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base) +/** + * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST payload + * + * The primary atomic state structure for a given MST payload. Stores information like current + * bandwidth allocation, intended action for this payload, etc. + */ struct drm_dp_mst_atomic_payload { + /** @port: The MST port assigned to this payload */ struct drm_dp_mst_port *port; /** @@ -551,16 +558,32 @@ struct drm_dp_mst_atomic_payload { * the immediate downstream DP Rx */ int time_slots; + /** @pbn: The payload bandwidth for this payload */ int pbn; + /** @dsc_enabled: Whether or not this payload has DSC enabled */ bool dsc_enabled; + + /** @next: The list node for this payload */ struct list_head next; }; +/** + * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic state + * + * This struct represents the atomic state of the toplevel DisplayPort MST manager + */ struct drm_dp_mst_topology_state { + /** @base: Base private state for atomic */ struct drm_private_state base; + + /** @payloads: The list of payloads being created/destroyed in this state */ struct list_head payloads; + /** @mgr: The topology manager */ struct drm_dp_mst_topology_mgr *mgr; + + /** @total_avail_slots: The total number of slots this topology can handle (63 or 64) */ u8 total_avail_slots; + /** @start_slot: The first usable time slot in this topology (1 or 0) */ u8 start_slot; }; From 0b4e477e08a14ef852d5a633cee10e4187730005 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:36 -0400 Subject: [PATCH 306/396] drm/display/dp_mst: Add helper for finding payloads in atomic MST state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already open-code this quite often, and will be iterating through payloads even more once we've moved all of the payload tracking into the atomic state. So, let's add a helper for doing this. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-8-lyude@redhat.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 109 ++++++++---------- 1 file changed, 45 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 8a2ddfde594a..1c054a5e2e77 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -1738,6 +1738,19 @@ drm_dp_mst_dump_port_topology_history(struct drm_dp_mst_port *port) {} #define save_port_topology_ref(port, type) #endif +static struct drm_dp_mst_atomic_payload * +drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state, + struct drm_dp_mst_port *port) +{ + struct drm_dp_mst_atomic_payload *payload; + + list_for_each_entry(payload, &state->payloads, next) + if (payload->port == port) + return payload; + + return NULL; +} + static void drm_dp_destroy_mst_branch_device(struct kref *kref) { struct drm_dp_mst_branch *mstb = @@ -4370,39 +4383,31 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, int pbn_div) { struct drm_dp_mst_topology_state *topology_state; - struct drm_dp_mst_atomic_payload *pos, *payload = NULL; - int prev_slots, prev_bw, req_slots; + struct drm_dp_mst_atomic_payload *payload = NULL; + int prev_slots = 0, prev_bw = 0, req_slots; topology_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(topology_state)) return PTR_ERR(topology_state); /* Find the current allocation for this port, if any */ - list_for_each_entry(pos, &topology_state->payloads, next) { - if (pos->port == port) { - payload = pos; - prev_slots = payload->time_slots; - prev_bw = payload->pbn; + payload = drm_atomic_get_mst_payload_state(topology_state, port); + if (payload) { + prev_slots = payload->time_slots; + prev_bw = payload->pbn; - /* - * This should never happen, unless the driver tries - * releasing and allocating the same timeslot allocation, - * which is an error - */ - if (WARN_ON(!prev_slots)) { - drm_err(mgr->dev, - "cannot allocate and release time slots on [MST PORT:%p] in the same state\n", - port); - return -EINVAL; - } - - break; + /* + * This should never happen, unless the driver tries + * releasing and allocating the same timeslot allocation, + * which is an error + */ + if (WARN_ON(!prev_slots)) { + drm_err(mgr->dev, + "cannot allocate and release time slots on [MST PORT:%p] in the same state\n", + port); + return -EINVAL; } } - if (!payload) { - prev_slots = 0; - prev_bw = 0; - } if (pbn_div <= 0) pbn_div = mgr->pbn_div; @@ -4463,30 +4468,24 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_port *port) { struct drm_dp_mst_topology_state *topology_state; - struct drm_dp_mst_atomic_payload *pos; - bool found = false; + struct drm_dp_mst_atomic_payload *payload; topology_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(topology_state)) return PTR_ERR(topology_state); - list_for_each_entry(pos, &topology_state->payloads, next) { - if (pos->port == port) { - found = true; - break; - } - } - if (WARN_ON(!found)) { + payload = drm_atomic_get_mst_payload_state(topology_state, port); + if (WARN_ON(!payload)) { drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst state %p\n", port, &topology_state->base); return -EINVAL; } - drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, pos->time_slots); - if (pos->time_slots) { + drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots); + if (payload->time_slots) { drm_dp_mst_put_port_malloc(port); - pos->time_slots = 0; - pos->pbn = 0; + payload->time_slots = 0; + payload->pbn = 0; } return 0; @@ -5182,18 +5181,8 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port, return 0; if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) { - bool found = false; - - list_for_each_entry(payload, &state->payloads, next) { - if (payload->port != port) - continue; - if (!payload->pbn) - return 0; - - found = true; - break; - } - if (!found) + payload = drm_atomic_get_mst_payload_state(state, port); + if (!payload) return 0; /* @@ -5348,34 +5337,26 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, bool enable) { struct drm_dp_mst_topology_state *mst_state; - struct drm_dp_mst_atomic_payload *pos; - bool found = false; + struct drm_dp_mst_atomic_payload *payload; int time_slots = 0; mst_state = drm_atomic_get_mst_topology_state(state, port->mgr); - if (IS_ERR(mst_state)) return PTR_ERR(mst_state); - list_for_each_entry(pos, &mst_state->payloads, next) { - if (pos->port == port) { - found = true; - break; - } - } - - if (!found) { + payload = drm_atomic_get_mst_payload_state(mst_state, port); + if (!payload) { drm_dbg_atomic(state->dev, "[MST PORT:%p] Couldn't find payload in mst state %p\n", port, mst_state); return -EINVAL; } - if (pos->dsc_enabled == enable) { + if (payload->dsc_enabled == enable) { drm_dbg_atomic(state->dev, "[MST PORT:%p] DSC flag is already set to %d, returning %d time slots\n", - port, enable, pos->time_slots); - time_slots = pos->time_slots; + port, enable, payload->time_slots); + time_slots = payload->time_slots; } if (enable) { @@ -5387,7 +5368,7 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, return -EINVAL; } - pos->dsc_enabled = enable; + payload->dsc_enabled = enable; return time_slots; } From a5c2c0d164e96d24f73faffcd3b7bbb607e701a9 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:37 -0400 Subject: [PATCH 307/396] drm/display/dp_mst: Add nonblocking helpers for DP MST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As Daniel Vetter pointed out, if we only use the atomic modesetting locks with MST it's technically possible for a driver with non-blocking modesets to race when it comes to MST displays - as we make the mistake of not doing our own CRTC commit tracking in the topology_state object. This could potentially cause problems if something like this happens: * User starts non-blocking commit to disable CRTC-1 on MST topology 1 * User starts non-blocking commit to enable CRTC-2 on MST topology 1 There's no guarantee here that the commit for disabling CRTC-2 will only occur after CRTC-1 has finished, since neither commit shares a CRTC - only the private modesetting object for MST. Keep in mind this likely isn't a problem for blocking modesets, only non-blocking. So, begin fixing this by keeping track of which CRTCs on a topology have changed by keeping track of which CRTCs we release or allocate timeslots on. As well, add some helpers for: * Setting up the drm_crtc_commit structs in the ->commit_setup hook * Waiting for any CRTC dependencies from the previous topology state v2: * Use drm_dp_mst_atomic_setup_commit() directly - Jani Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-9-lyude@redhat.com --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +- drivers/gpu/drm/display/drm_dp_mst_topology.c | 93 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_display.c | 6 ++ drivers/gpu/drm/nouveau/dispnv50/disp.c | 7 ++ include/drm/display/drm_dp_mst_helper.h | 15 +++ 5 files changed, 124 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index cd30b02af8ee..c97a4d759b94 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2808,7 +2808,8 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { - .atomic_commit_tail = amdgpu_dm_atomic_commit_tail + .atomic_commit_tail = amdgpu_dm_atomic_commit_tail, + .atomic_commit_setup = drm_dp_mst_atomic_setup_commit, }; static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) @@ -7959,6 +7960,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) DRM_ERROR("Waiting for fences timed out!"); drm_atomic_helper_update_legacy_modeset_state(dev, state); + drm_dp_mst_atomic_wait_for_dependencies(state); dm_state = dm_atomic_get_new_state(state); if (dm_state && dm_state->context) { @@ -8357,7 +8359,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dc_release_state(dc_state_temp); } - static int dm_force_atomic_commit(struct drm_connector *connector) { int ret = 0; diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 1c054a5e2e77..d701e5b819b8 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4384,12 +4384,16 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, { struct drm_dp_mst_topology_state *topology_state; struct drm_dp_mst_atomic_payload *payload = NULL; + struct drm_connector_state *conn_state; int prev_slots = 0, prev_bw = 0, req_slots; topology_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(topology_state)) return PTR_ERR(topology_state); + conn_state = drm_atomic_get_new_connector_state(state, port->connector); + topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc); + /* Find the current allocation for this port, if any */ payload = drm_atomic_get_mst_payload_state(topology_state, port); if (payload) { @@ -4469,11 +4473,15 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, { struct drm_dp_mst_topology_state *topology_state; struct drm_dp_mst_atomic_payload *payload; + struct drm_connector_state *conn_state; topology_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(topology_state)) return PTR_ERR(topology_state); + conn_state = drm_atomic_get_old_connector_state(state, port->connector); + topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc); + payload = drm_atomic_get_mst_payload_state(topology_state, port); if (WARN_ON(!payload)) { drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst state %p\n", @@ -4492,6 +4500,83 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_dp_atomic_release_time_slots); +/** + * drm_dp_mst_atomic_setup_commit() - setup_commit hook for MST helpers + * @state: global atomic state + * + * This function saves all of the &drm_crtc_commit structs in an atomic state that touch any CRTCs + * currently assigned to an MST topology. Drivers must call this hook from their + * &drm_mode_config_helper_funcs.atomic_commit_setup hook. + * + * Returns: + * 0 if all CRTC commits were retrieved successfully, negative error code otherwise + */ +int drm_dp_mst_atomic_setup_commit(struct drm_atomic_state *state) +{ + struct drm_dp_mst_topology_mgr *mgr; + struct drm_dp_mst_topology_state *mst_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i, j, commit_idx, num_commit_deps; + + for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { + if (!mst_state->pending_crtc_mask) + continue; + + num_commit_deps = hweight32(mst_state->pending_crtc_mask); + mst_state->commit_deps = kmalloc_array(num_commit_deps, + sizeof(*mst_state->commit_deps), GFP_KERNEL); + if (!mst_state->commit_deps) + return -ENOMEM; + mst_state->num_commit_deps = num_commit_deps; + + commit_idx = 0; + for_each_new_crtc_in_state(state, crtc, crtc_state, j) { + if (mst_state->pending_crtc_mask & drm_crtc_mask(crtc)) { + mst_state->commit_deps[commit_idx++] = + drm_crtc_commit_get(crtc_state->commit); + } + } + } + + return 0; +} +EXPORT_SYMBOL(drm_dp_mst_atomic_setup_commit); + +/** + * drm_dp_mst_atomic_wait_for_dependencies() - Wait for all pending commits on MST topologies + * @state: global atomic state + * + * Goes through any MST topologies in this atomic state, and waits for any pending commits which + * touched CRTCs that were/are on an MST topology to be programmed to hardware and flipped to before + * returning. This is to prevent multiple non-blocking commits affecting an MST topology from racing + * with eachother by forcing them to be executed sequentially in situations where the only resources + * the modeset objects in these commits share are an MST topology. + * + * This function also prepares the new MST state for commit by performing some state preparation + * which can't be done until this point, such as reading back the final VC start slots (which are + * determined at commit-time) from the previous state. + * + * All MST drivers must call this function after calling drm_atomic_helper_wait_for_dependencies(), + * or whatever their equivalent of that is. + */ +void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state) +{ + struct drm_dp_mst_topology_state *old_mst_state; + struct drm_dp_mst_topology_mgr *mgr; + int i, j, ret; + + for_each_old_mst_mgr_in_state(state, mgr, old_mst_state, i) { + for (j = 0; j < old_mst_state->num_commit_deps; j++) { + ret = drm_crtc_commit_wait(old_mst_state->commit_deps[j]); + if (ret < 0) + drm_err(state->dev, "Failed to wait for %s: %d\n", + old_mst_state->commit_deps[j]->crtc->name, ret); + } + } +} +EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies); + /** * drm_dp_mst_update_slots() - updates the slot info depending on the DP ecoding format * @mst_state: mst_state to update @@ -5067,6 +5152,9 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj) __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); INIT_LIST_HEAD(&state->payloads); + state->commit_deps = NULL; + state->num_commit_deps = 0; + state->pending_crtc_mask = 0; list_for_each_entry(pos, &old_state->payloads, next) { /* Prune leftover freed timeslot allocations */ @@ -5099,6 +5187,7 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, struct drm_dp_mst_topology_state *mst_state = to_dp_mst_topology_state(state); struct drm_dp_mst_atomic_payload *pos, *tmp; + int i; list_for_each_entry_safe(pos, tmp, &mst_state->payloads, next) { /* We only keep references to ports with non-zero VCPIs */ @@ -5107,6 +5196,10 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, kfree(pos); } + for (i = 0; i < mst_state->num_commit_deps; i++) + drm_crtc_commit_put(mst_state->commit_deps[i]); + + kfree(mst_state->commit_deps); kfree(mst_state); } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index bf170bd83ef7..2a45a25e42fb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7532,6 +7532,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_atomic_commit_fence_wait(state); drm_atomic_helper_wait_for_dependencies(&state->base); + drm_dp_mst_atomic_wait_for_dependencies(&state->base); if (state->modeset) wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET); @@ -8600,6 +8601,10 @@ out: return ret; } +static const struct drm_mode_config_helper_funcs intel_mode_config_funcs = { + .atomic_commit_setup = drm_dp_mst_atomic_setup_commit, +}; + static void intel_mode_config_init(struct drm_i915_private *i915) { struct drm_mode_config *mode_config = &i915->drm.mode_config; @@ -8614,6 +8619,7 @@ static void intel_mode_config_init(struct drm_i915_private *i915) mode_config->prefer_shadow = 1; mode_config->funcs = &intel_mode_funcs; + mode_config->helper_private = &intel_mode_config_funcs; mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 1d54f2cd38b2..c55af5d78ea2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -2136,6 +2136,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) nv50_crc_atomic_stop_reporting(state); drm_atomic_helper_wait_for_fences(dev, state, false); drm_atomic_helper_wait_for_dependencies(state); + drm_dp_mst_atomic_wait_for_dependencies(state); drm_atomic_helper_update_legacy_modeset_state(dev, state); drm_atomic_helper_calc_timestamping_constants(state); @@ -2616,6 +2617,11 @@ nv50_disp_func = { .atomic_state_free = nv50_disp_atomic_state_free, }; +static const struct drm_mode_config_helper_funcs +nv50_disp_helper_func = { + .atomic_commit_setup = drm_dp_mst_atomic_setup_commit, +}; + /****************************************************************************** * Init *****************************************************************************/ @@ -2699,6 +2705,7 @@ nv50_display_create(struct drm_device *dev) nouveau_display(dev)->fini = nv50_display_fini; disp->disp = &nouveau_display(dev)->disp; dev->mode_config.funcs = &nv50_disp_func; + dev->mode_config.helper_private = &nv50_disp_helper_func; dev->mode_config.quirk_addfb_prefer_xbgr_30bpp = true; dev->mode_config.normalize_zpos = true; diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 3b155ad3eee4..0ef7d0e6cf0c 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -581,6 +581,19 @@ struct drm_dp_mst_topology_state { /** @mgr: The topology manager */ struct drm_dp_mst_topology_mgr *mgr; + /** + * @pending_crtc_mask: A bitmask of all CRTCs this topology state touches, drivers may + * modify this to add additional dependencies if needed. + */ + u32 pending_crtc_mask; + /** + * @commit_deps: A list of all CRTC commits affecting this topology, this field isn't + * populated until drm_dp_mst_atomic_wait_for_dependencies() is called. + */ + struct drm_crtc_commit **commit_deps; + /** @num_commit_deps: The number of CRTC commits in @commit_deps */ + size_t num_commit_deps; + /** @total_avail_slots: The total number of slots this topology can handle (63 or 64) */ u8 total_avail_slots; /** @start_slot: The first usable time slot in this topology (1 or 0) */ @@ -890,6 +903,8 @@ int __must_check drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); +void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state); +int __must_check drm_dp_mst_atomic_setup_commit(struct drm_atomic_state *state); int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, bool power_up); int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, From ffac9721939dca3f0ac7bfa90f3dc484b19c2706 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:38 -0400 Subject: [PATCH 308/396] drm/display/dp_mst: Don't open code modeset checks for releasing time slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm not sure why, but at the time I originally wrote the find/release time slot helpers I thought we should avoid keeping modeset tracking out of the MST helpers. In retrospect though there's no actual good reason to do this, and the logic has ended up being identical across all the drivers using the helpers. Also, it needs to be fixed anyway so we don't break things when going atomic-only with MST. So, let's just move this code into drm_dp_atomic_release_time_slots() and stop open coding it. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-10-lyude@redhat.com --- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 29 +++---------------- drivers/gpu/drm/display/drm_dp_mst_topology.c | 21 ++++++++++++-- drivers/gpu/drm/i915/display/intel_dp_mst.c | 24 +-------------- drivers/gpu/drm/nouveau/dispnv50/disp.c | 21 -------------- 4 files changed, 23 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 655d63b20b33..7a0d6cfa77f5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -447,34 +447,13 @@ dm_dp_mst_detect(struct drm_connector *connector, } static int dm_dp_mst_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) + struct drm_atomic_state *state) { - struct drm_connector_state *new_conn_state = - drm_atomic_get_new_connector_state(state, connector); - struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(state, connector); struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct drm_crtc_state *new_crtc_state; - struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_port *mst_port; + struct drm_dp_mst_topology_mgr *mst_mgr = &aconnector->mst_port->mst_mgr; + struct drm_dp_mst_port *mst_port = aconnector->port; - mst_port = aconnector->port; - mst_mgr = &aconnector->mst_port->mst_mgr; - - if (!old_conn_state->crtc) - return 0; - - if (new_conn_state->crtc) { - new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); - if (!new_crtc_state || - !drm_atomic_crtc_needs_modeset(new_crtc_state) || - new_crtc_state->enable) - return 0; - } - - return drm_dp_atomic_release_time_slots(state, - mst_mgr, - mst_port); + return drm_dp_atomic_release_time_slots(state, mst_mgr, mst_port); } static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = { diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index d701e5b819b8..aa6dcd9ff6a5 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4473,14 +4473,29 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, { struct drm_dp_mst_topology_state *topology_state; struct drm_dp_mst_atomic_payload *payload; - struct drm_connector_state *conn_state; + struct drm_connector_state *old_conn_state, *new_conn_state; + + old_conn_state = drm_atomic_get_old_connector_state(state, port->connector); + if (!old_conn_state->crtc) + return 0; + + /* If the CRTC isn't disabled by this state, don't release it's payload */ + new_conn_state = drm_atomic_get_new_connector_state(state, port->connector); + if (new_conn_state->crtc) { + struct drm_crtc_state *crtc_state = + drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + + if (!crtc_state || + !drm_atomic_crtc_needs_modeset(crtc_state) || + crtc_state->enable) + return 0; + } topology_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(topology_state)) return PTR_ERR(topology_state); - conn_state = drm_atomic_get_old_connector_state(state, port->connector); - topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc); + topology_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc); payload = drm_atomic_get_mst_payload_state(topology_state, port); if (WARN_ON(!payload)) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 1cebbc51d8fa..1b067cd73261 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -308,13 +308,10 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, struct drm_atomic_state *_state) { struct intel_atomic_state *state = to_intel_atomic_state(_state); - struct drm_connector_state *new_conn_state = - drm_atomic_get_new_connector_state(&state->base, connector); struct drm_connector_state *old_conn_state = drm_atomic_get_old_connector_state(&state->base, connector); struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_crtc *new_crtc = new_conn_state->crtc; struct drm_dp_mst_topology_mgr *mgr; int ret; @@ -326,27 +323,8 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, if (ret) return ret; - if (!old_conn_state->crtc) - return 0; - - /* We only want to free VCPI if this state disables the CRTC on this - * connector - */ - if (new_crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc); - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - - if (!crtc_state || - !drm_atomic_crtc_needs_modeset(&crtc_state->uapi) || - crtc_state->uapi.enable) - return 0; - } - mgr = &enc_to_mst(to_intel_encoder(old_conn_state->best_encoder))->primary->dp.mst_mgr; - ret = drm_dp_atomic_release_time_slots(&state->base, mgr, intel_connector->port); - - return ret; + return drm_dp_atomic_release_time_slots(&state->base, mgr, intel_connector->port); } static void clear_act_sent(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index c55af5d78ea2..5669c8d747d7 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1255,27 +1255,6 @@ nv50_mstc_atomic_check(struct drm_connector *connector, { struct nv50_mstc *mstc = nv50_mstc(connector); struct drm_dp_mst_topology_mgr *mgr = &mstc->mstm->mgr; - struct drm_connector_state *new_conn_state = - drm_atomic_get_new_connector_state(state, connector); - struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(state, connector); - struct drm_crtc_state *crtc_state; - struct drm_crtc *new_crtc = new_conn_state->crtc; - - if (!old_conn_state->crtc) - return 0; - - /* We only want to free VCPI if this state disables the CRTC on this - * connector - */ - if (new_crtc) { - crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); - - if (!crtc_state || - !drm_atomic_crtc_needs_modeset(crtc_state) || - crtc_state->enable) - return 0; - } return drm_dp_atomic_release_time_slots(state, mgr, mstc->port); } From 083351e963865a7eab55158042b81b8f8c0316b6 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:39 -0400 Subject: [PATCH 309/396] drm/display/dp_mst: Fix modeset tracking in drm_dp_atomic_release_vcpi_slots() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently with the MST helpers we avoid releasing payloads _and_ avoid pulling in the MST state if there aren't any actual payload changes. While we want to keep the first step, we need to now make sure that we're always pulling in the MST state on all modesets that can modify payloads - even if the resulting payloads in the atomic state are identical to the previous ones. This is mainly to make it so that if a CRTC is still assigned to a connector but is set to DPMS off, the CRTC still holds it's payload allocation in the atomic state and still appropriately pulls in the MST state for commit tracking. Otherwise, we'll occasionally forget to update MST payloads from changes caused by non-atomic DPMS changes. Doing this also allows us to track bandwidth limitations in a state correctly even between DPMS changes, so that there's no chance of a simple ->active change being rejected by the atomic check. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-11-lyude@redhat.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index aa6dcd9ff6a5..2f7c43f88d74 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4474,6 +4474,7 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_state *topology_state; struct drm_dp_mst_atomic_payload *payload; struct drm_connector_state *old_conn_state, *new_conn_state; + bool update_payload = true; old_conn_state = drm_atomic_get_old_connector_state(state, port->connector); if (!old_conn_state->crtc) @@ -4485,10 +4486,12 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); - if (!crtc_state || - !drm_atomic_crtc_needs_modeset(crtc_state) || - crtc_state->enable) + /* No modeset means no payload changes, so it's safe to not pull in the MST state */ + if (!crtc_state || !drm_atomic_crtc_needs_modeset(crtc_state)) return 0; + + if (!crtc_state->mode_changed && !crtc_state->connectors_changed) + update_payload = false; } topology_state = drm_atomic_get_mst_topology_state(state, mgr); @@ -4496,6 +4499,8 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, return PTR_ERR(topology_state); topology_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc); + if (!update_payload) + return 0; payload = drm_atomic_get_mst_payload_state(topology_state, port); if (WARN_ON(!payload)) { From 11d2738940ebeb3fd3abc78d44684d5edb400a6e Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:40 -0400 Subject: [PATCH 310/396] drm/nouveau/kms: Cache DP encoders in nouveau_connector Post-NV50, the only kind of encoder you'll find for DP connectors on Nvidia GPUs are SORs (serial output resources). Because SORs have fixed associations with their connectors, we can correctly assume that any DP connector on a nvidia GPU will have exactly one SOR encoder routed to it for DisplayPort. Since we're going to need to be able to retrieve this fixed SOR DP encoder much more often as a result of hooking up MST helpers for tracking SST<->MST transitions in atomic states, let's simply cache this encoder in nouveau_connector for any DP connectors on the system to avoid looking it up each time. This isn't safe for NV50 since PIORs then come into play, however there's no code pre-NV50 that would need to look this up anyhow - so it's not really an issue. Signed-off-by: Lyude Paul <lyude@redhat.com> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-12-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 +++- drivers/gpu/drm/nouveau/nouveau_connector.h | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 8100c75ee731..b8ee2173ca8f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1368,7 +1368,7 @@ nouveau_connector_create(struct drm_device *dev, return ERR_PTR(-ENOMEM); } drm_dp_aux_init(&nv_connector->aux); - fallthrough; + break; default: funcs = &nouveau_connector_funcs; break; @@ -1431,6 +1431,8 @@ nouveau_connector_create(struct drm_device *dev, switch (type) { case DRM_MODE_CONNECTOR_DisplayPort: + nv_connector->dp_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP); + fallthrough; case DRM_MODE_CONNECTOR_eDP: drm_dp_cec_register_connector(&nv_connector->aux, connector); break; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index 4bf0c703eee7..f4e17ff68bf9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -128,6 +128,9 @@ struct nouveau_connector { struct drm_dp_aux aux; + /* The fixed DP encoder for this connector, if there is one */ + struct nouveau_encoder *dp_encoder; + int dithering_mode; int scaling_mode; From 21167510605470d53c94e7162ae886c8fb67d93d Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:41 -0400 Subject: [PATCH 311/396] drm/nouveau/kms: Pull mst state in for all modesets Since we're going to be relying on atomic locking for payloads now (and the MST mgr needs to track CRTCs), pull in the topology state for all modesets in nv50_msto_atomic_check(). Signed-off-by: Lyude Paul <lyude@redhat.com> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-13-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 5669c8d747d7..24807aa9da5f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1049,7 +1049,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, if (ret) return ret; - if (!crtc_state->mode_changed && !crtc_state->connectors_changed) + if (!drm_atomic_crtc_needs_modeset(crtc_state)) return 0; /* From a76eb4297f90301fa9e4c888fb06749ef1be1c86 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:42 -0400 Subject: [PATCH 312/396] drm/display/dp_mst: Add helpers for serializing SST <-> MST transitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's another kind of situation where we could potentially race with nonblocking modesets and MST, especially if we were to only use the locking provided by atomic modesetting: * Display 1 begins as enabled on DP-1 in SST mode * Display 1 switches to MST mode, exposes one sink in MST mode * Userspace does non-blocking modeset to disable the SST display * Userspace does non-blocking modeset to enable the MST display with a different CRTC, but the SST display hasn't been fully taken down yet * Execution order between the last two commits isn't guaranteed since they share no drm resources We can fix this however, by ensuring that we always pull in the atomic topology state whenever a connector capable of driving an MST display performs its atomic check - and then tracking CRTC commits happening on the SST connector in the MST topology state. So, let's add some simple helpers for doing that and hook them up in various drivers. v2: * Use intel_dp_mst_source_support() to check for MST support in i915, fixes CI failures Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-14-lyude@redhat.com --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++ drivers/gpu/drm/display/drm_dp_mst_topology.c | 59 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 9 +++ drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.h | 2 + drivers/gpu/drm/nouveau/nouveau_connector.c | 14 +++++ include/drm/display/drm_dp_mst_helper.h | 2 + 7 files changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c97a4d759b94..789748739d79 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6291,10 +6291,17 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn, drm_atomic_get_old_connector_state(state, conn); struct drm_crtc *crtc = new_con_state->crtc; struct drm_crtc_state *new_crtc_state; + struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); int ret; trace_amdgpu_dm_connector_atomic_check(new_con_state); + if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + ret = drm_dp_mst_root_conn_atomic_check(new_con_state, &aconn->mst_mgr); + if (ret < 0) + return ret; + } + if (!crtc) return 0; diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 2f7c43f88d74..97e8f8a83ed4 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4597,6 +4597,65 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state) } EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies); +/** + * drm_dp_mst_root_conn_atomic_check() - Serialize CRTC commits on MST-capable connectors operating + * in SST mode + * @new_conn_state: The new connector state of the &drm_connector + * @mgr: The MST topology manager for the &drm_connector + * + * Since MST uses fake &drm_encoder structs, the generic atomic modesetting code isn't able to + * serialize non-blocking commits happening on the real DP connector of an MST topology switching + * into/away from MST mode - as the CRTC on the real DP connector and the CRTCs on the connector's + * MST topology will never share the same &drm_encoder. + * + * This function takes care of this serialization issue, by checking a root MST connector's atomic + * state to determine if it is about to have a modeset - and then pulling in the MST topology state + * if so, along with adding any relevant CRTCs to &drm_dp_mst_topology_state.pending_crtc_mask. + * + * Drivers implementing MST must call this function from the + * &drm_connector_helper_funcs.atomic_check hook of any physical DP &drm_connector capable of + * driving MST sinks. + * + * Returns: + * 0 on success, negative error code otherwise + */ +int drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state, + struct drm_dp_mst_topology_mgr *mgr) +{ + struct drm_atomic_state *state = new_conn_state->state; + struct drm_connector_state *old_conn_state = + drm_atomic_get_old_connector_state(state, new_conn_state->connector); + struct drm_crtc_state *crtc_state; + struct drm_dp_mst_topology_state *mst_state = NULL; + + if (new_conn_state->crtc) { + crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) { + mst_state = drm_atomic_get_mst_topology_state(state, mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + mst_state->pending_crtc_mask |= drm_crtc_mask(new_conn_state->crtc); + } + } + + if (old_conn_state->crtc) { + crtc_state = drm_atomic_get_new_crtc_state(state, old_conn_state->crtc); + if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) { + if (!mst_state) { + mst_state = drm_atomic_get_mst_topology_state(state, mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + } + + mst_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc); + } + } + + return 0; +} +EXPORT_SYMBOL(drm_dp_mst_root_conn_atomic_check); + /** * drm_dp_mst_update_slots() - updates the slot info depending on the DP ecoding format * @mst_state: mst_state to update diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 32292c0be2bd..a4e113253df3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4992,12 +4992,21 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, { struct drm_i915_private *dev_priv = to_i915(conn->dev); struct intel_atomic_state *state = to_intel_atomic_state(_state); + struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(_state, conn); + struct intel_connector *intel_conn = to_intel_connector(conn); + struct intel_dp *intel_dp = enc_to_intel_dp(intel_conn->encoder); int ret; ret = intel_digital_connector_atomic_check(conn, &state->base); if (ret) return ret; + if (intel_dp_mst_source_support(intel_dp)) { + ret = drm_dp_mst_root_conn_atomic_check(conn_state, &intel_dp->mst_mgr); + if (ret) + return ret; + } + /* * We don't enable port sync on BDW due to missing w/as and * due to not having adjusted the modeset sequence appropriately. diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 24807aa9da5f..7e9a0b50bb42 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1813,7 +1813,7 @@ nv50_sor_func = { .destroy = nv50_sor_destroy, }; -static bool nv50_has_mst(struct nouveau_drm *drm) +bool nv50_has_mst(struct nouveau_drm *drm) { struct nvkm_bios *bios = nvxx_bios(&drm->client.device); u32 data; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h index 38dec11e7dda..9d66c9c726c3 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h @@ -106,6 +106,8 @@ void nv50_dmac_destroy(struct nv50_dmac *); */ struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder); +bool nv50_has_mst(struct nouveau_drm *drm); + u32 *evo_wait(struct nv50_dmac *, int nr); void evo_kick(u32 *, struct nv50_dmac *); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index b8ee2173ca8f..1991bbb1d05c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1106,11 +1106,25 @@ nouveau_connector_best_encoder(struct drm_connector *connector) return NULL; } +static int +nouveau_connector_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) +{ + struct nouveau_connector *nv_conn = nouveau_connector(connector); + struct drm_connector_state *conn_state = + drm_atomic_get_new_connector_state(state, connector); + + if (!nv_conn->dp_encoder || !nv50_has_mst(nouveau_drm(connector->dev))) + return 0; + + return drm_dp_mst_root_conn_atomic_check(conn_state, &nv_conn->dp_encoder->dp.mstm->mgr); +} + static const struct drm_connector_helper_funcs nouveau_connector_helper_funcs = { .get_modes = nouveau_connector_get_modes, .mode_valid = nouveau_connector_mode_valid, .best_encoder = nouveau_connector_best_encoder, + .atomic_check = nouveau_connector_atomic_check, }; static const struct drm_connector_funcs diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 0ef7d0e6cf0c..b9c361b242ea 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -911,6 +911,8 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, struct drm_dp_query_stream_enc_status_ack_reply *status); int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); +int __must_check drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state, + struct drm_dp_mst_topology_mgr *mgr); void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); From 2482fceed27b6951287e92e9f733533a657c2923 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:43 -0400 Subject: [PATCH 313/396] drm/display/dp_mst: Drop all ports from topology on CSNs before queueing link address work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to start cutting down on all of the places that we use port validation, so that ports may be removed from the topology as quickly as possible to minimize the number of errors we run into as a result of being out of sync with the current topology status. This isn't a very typical scenario and I don't think I've ever even run into it - but since the next commit is going to make some changes to payload updates depending on their hotplug status I think it's a probably good idea to take precautions. Let's do this with CSNs by moving some code around so that we only queue link address probing work at the end of handling all CSNs - allowing us to make sure we drop as many topology references as we can beforehand. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-15-lyude@redhat.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 97e8f8a83ed4..a5460cadf2c8 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -2509,7 +2509,7 @@ fail_put: return ret; } -static void +static int drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, struct drm_dp_connection_status_notify *conn_stat) { @@ -2522,7 +2522,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, port = drm_dp_get_port(mstb, conn_stat->port_number); if (!port) - return; + return 0; if (port->connector) { if (!port->input && conn_stat->input_port) { @@ -2575,8 +2575,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, out: drm_dp_mst_topology_put_port(port); - if (dowork) - queue_work(system_long_wq, &mstb->mgr->work); + return dowork; } static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_topology_mgr *mgr, @@ -4060,7 +4059,7 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_branch *mstb = NULL; struct drm_dp_sideband_msg_req_body *msg = &up_req->msg; struct drm_dp_sideband_msg_hdr *hdr = &up_req->hdr; - bool hotplug = false; + bool hotplug = false, dowork = false; if (hdr->broadcast) { const u8 *guid = NULL; @@ -4083,11 +4082,14 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr, /* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */ if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) { - drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat); + dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat); hotplug = true; } drm_dp_mst_topology_put_mstb(mstb); + + if (dowork) + queue_work(system_long_wq, &mgr->work); return hotplug; } From 6366fc70deb9aaf1db4a46916af14fa3c5a115ab Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:44 -0400 Subject: [PATCH 314/396] drm/display/dp_mst: Maintain time slot allocations when deleting payloads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, we set drm_dp_atomic_payload->time_slots to 0 in order to indicate that we're about to delete a payload in the current atomic state. Since we're going to be dropping all of the legacy code for handling the payload table however, we need to be able to ensure that we still keep track of the current time slot allocations for each payload so we can reuse this info when asking the root MST hub to delete payloads. We'll also be using it to recalculate the start slots of each VC. So, let's keep track of the intent of a payload in drm_dp_atomic_payload by adding ->delete, which we set whenever we're planning on deleting a payload during the current atomic commit. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-16-lyude@redhat.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 14 +++++++------- include/drm/display/drm_dp_mst_helper.h | 5 ++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index a5460cadf2c8..c4073d733c59 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4407,7 +4407,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, * releasing and allocating the same timeslot allocation, * which is an error */ - if (WARN_ON(!prev_slots)) { + if (drm_WARN_ON(mgr->dev, payload->delete)) { drm_err(mgr->dev, "cannot allocate and release time slots on [MST PORT:%p] in the same state\n", port); @@ -4512,10 +4512,10 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, } drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots); - if (payload->time_slots) { + if (!payload->delete) { drm_dp_mst_put_port_malloc(port); - payload->time_slots = 0; payload->pbn = 0; + payload->delete = true; } return 0; @@ -5239,7 +5239,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj) list_for_each_entry(pos, &old_state->payloads, next) { /* Prune leftover freed timeslot allocations */ - if (!pos->time_slots) + if (pos->delete) continue; payload = kmemdup(pos, sizeof(*payload), GFP_KERNEL); @@ -5271,8 +5271,8 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, int i; list_for_each_entry_safe(pos, tmp, &mst_state->payloads, next) { - /* We only keep references to ports with non-zero VCPIs */ - if (pos->time_slots) + /* We only keep references to ports with active payloads */ + if (!pos->delete) drm_dp_mst_put_port_malloc(pos->port); kfree(pos); } @@ -5400,7 +5400,7 @@ drm_dp_mst_atomic_check_payload_alloc_limits(struct drm_dp_mst_topology_mgr *mgr list_for_each_entry(payload, &mst_state->payloads, next) { /* Releasing payloads is always OK-even if the port is gone */ - if (!payload->time_slots) { + if (payload->delete) { drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all time slots\n", payload->port); continue; diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index b9c361b242ea..8b847836a0b4 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -560,8 +560,11 @@ struct drm_dp_mst_atomic_payload { int time_slots; /** @pbn: The payload bandwidth for this payload */ int pbn; + + /** @delete: Whether or not we intend to delete this payload during this atomic commit */ + bool delete : 1; /** @dsc_enabled: Whether or not this payload has DSC enabled */ - bool dsc_enabled; + bool dsc_enabled : 1; /** @next: The list node for this payload */ struct list_head next; From 01ad1d9c2888d51f2fb5b5ac88af8bd47d76937e Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:45 -0400 Subject: [PATCH 315/396] drm/radeon: Drop legacy MST support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right now, radeon is technically the only non-atomic driver still making use of the MST helpers - and thus the final user of all of the legacy MST helpers. Originally I was going to look into seeing if we could move legacy MST into the radeon driver itself, however: * SI and CIK both can use amdgpu, which still supports MST * It currently doesn't work according to my own testing. I'm sure with some troubleshooting we could likely fix it, but that brings me to point #2: * It was never actually enabled by default, and is still marked as experimental in the module parameter description * If people were using it, someone probably would have probably seen a bug report about how it is currently not functional by now. That certainly doesn't appear to be the case, since before getting access to my own hardware I had to go out of my way to try finding someone to help test whether this legacy MST code even works - even amongst AMD employees. * Getting rid of this code and only having atomic versions of the MST helpers to maintain is likely going to be a lot easier in the long run, and will make it a lot easier for others contributing to this code to follow along with what's happening. FWIW - if anyone still wants this code to be in the tree and has a good idea of how to support this without needing to maintain the legacy MST helpers (trying to move them would probably be acceptable), I'm happy to suggestions. But my hope is that we can just drop this code and forget about it. I've already run this idea by Harry Wentland and Alex Deucher a few times as well. Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-17-lyude@redhat.com --- drivers/gpu/drm/radeon/Makefile | 2 +- drivers/gpu/drm/radeon/atombios_crtc.c | 11 +- drivers/gpu/drm/radeon/atombios_encoders.c | 59 -- drivers/gpu/drm/radeon/radeon_atombios.c | 2 - drivers/gpu/drm/radeon/radeon_connectors.c | 61 +- drivers/gpu/drm/radeon/radeon_device.c | 1 - drivers/gpu/drm/radeon/radeon_dp_mst.c | 778 --------------------- drivers/gpu/drm/radeon/radeon_drv.c | 4 - drivers/gpu/drm/radeon/radeon_encoders.c | 14 +- drivers/gpu/drm/radeon/radeon_irq_kms.c | 10 +- drivers/gpu/drm/radeon/radeon_mode.h | 40 -- 11 files changed, 7 insertions(+), 975 deletions(-) delete mode 100644 drivers/gpu/drm/radeon/radeon_dp_mst.c diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index e3ab3aca1396..bb4e56f2f170 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \ trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \ ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \ - radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o + radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 69f1bc073902..d28d3acb3ba1 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -617,13 +617,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, } } - if (radeon_encoder->is_mst_encoder) { - struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv; - struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv; - - dp_clock = dig_connector->dp_clock; - } - /* use recommended ref_div for ss */ if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { if (radeon_crtc->ss_enabled) { @@ -972,9 +965,7 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_ radeon_crtc->bpc = 8; radeon_crtc->ss_enabled = false; - if (radeon_encoder->is_mst_encoder) { - radeon_dp_mst_prepare_pll(crtc, mode); - } else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || + if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) { struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct drm_connector *connector = diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index c93040e60d04..0eae05dfb385 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -667,15 +667,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) struct drm_connector *connector; struct radeon_connector *radeon_connector; struct radeon_connector_atom_dig *dig_connector; - struct radeon_encoder_atom_dig *dig_enc; - if (radeon_encoder_is_digital(encoder)) { - dig_enc = radeon_encoder->enc_priv; - if (dig_enc->active_mst_links) - return ATOM_ENCODER_MODE_DP_MST; - } - if (radeon_encoder->is_mst_encoder || radeon_encoder->offset) - return ATOM_ENCODER_MODE_DP_MST; /* dp bridges are always DP */ if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) return ATOM_ENCODER_MODE_DP; @@ -1723,10 +1715,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - /* don't power off encoders with active MST links */ - if (dig->active_mst_links) - return; - if (ASIC_IS_DCE4(rdev)) { if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1992,53 +1980,6 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); } -void -atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe) -{ - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); - int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); - uint8_t frev, crev; - union crtc_source_param args; - - memset(&args, 0, sizeof(args)); - - if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) - return; - - if (frev != 1 && crev != 2) - DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev); - - args.v2.ucCRTC = radeon_crtc->crtc_id; - args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST; - - switch (fe) { - case 0: - args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; - break; - case 1: - args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; - break; - case 2: - args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; - break; - case 3: - args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; - break; - case 4: - args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; - break; - case 5: - args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; - break; - case 6: - args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID; - break; - } - atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); -} - static void atombios_apply_encoder_quirks(struct drm_encoder *encoder, struct drm_display_mode *mode) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 28c4413f4dc8..204127bad89c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -826,8 +826,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) } radeon_link_encoder_connector(dev); - - radeon_setup_mst_connector(dev); return true; } diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 58db79921cd3..f7431d224604 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -37,33 +37,12 @@ #include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> -static int radeon_dp_handle_hpd(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - int ret; - - ret = radeon_dp_mst_check_status(radeon_connector); - if (ret == -EINVAL) - return 1; - return 0; -} void radeon_connector_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); - if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { - struct radeon_connector_atom_dig *dig_connector = - radeon_connector->con_priv; - - if (radeon_connector->is_mst_connector) - return; - if (dig_connector->is_mst) { - radeon_dp_handle_hpd(connector); - return; - } - } /* bail if the connector does not have hpd pin, e.g., * VGA, TV, etc. */ @@ -1664,9 +1643,6 @@ radeon_dp_detect(struct drm_connector *connector, bool force) struct drm_encoder *encoder = radeon_best_single_encoder(connector); int r; - if (radeon_dig_connector->is_mst) - return connector_status_disconnected; - if (!drm_kms_helper_is_poll_worker()) { r = pm_runtime_get_sync(connector->dev->dev); if (r < 0) { @@ -1729,21 +1705,12 @@ radeon_dp_detect(struct drm_connector *connector, bool force) radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { ret = connector_status_connected; - if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) radeon_dp_getdpcd(radeon_connector); - r = radeon_dp_mst_probe(radeon_connector); - if (r == 1) - ret = connector_status_disconnected; - } } else { if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { - if (radeon_dp_getdpcd(radeon_connector)) { - r = radeon_dp_mst_probe(radeon_connector); - if (r == 1) - ret = connector_status_disconnected; - else - ret = connector_status_connected; - } + if (radeon_dp_getdpcd(radeon_connector)) + ret = connector_status_connected; } else { /* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */ if (radeon_ddc_probe(radeon_connector, false)) @@ -2561,25 +2528,3 @@ radeon_add_legacy_connector(struct drm_device *dev, connector->display_info.subpixel_order = subpixel_order; drm_connector_register(connector); } - -void radeon_setup_mst_connector(struct drm_device *dev) -{ - struct radeon_device *rdev = dev->dev_private; - struct drm_connector *connector; - struct radeon_connector *radeon_connector; - - if (!ASIC_IS_DCE5(rdev)) - return; - - if (radeon_mst == 0) - return; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - radeon_connector = to_radeon_connector(connector); - - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) - continue; - - radeon_dp_mst_init(radeon_connector); - } -} diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 2b12389f841a..a215ff1363cd 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1438,7 +1438,6 @@ int radeon_device_init(struct radeon_device *rdev, goto failed; radeon_gem_debugfs_init(rdev); - radeon_mst_debugfs_init(rdev); if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { /* Acceleration not working on AGP card try again diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c deleted file mode 100644 index 54ced1f4ff67..000000000000 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ /dev/null @@ -1,778 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include <drm/display/drm_dp_mst_helper.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_file.h> -#include <drm/drm_probe_helper.h> - -#include "atom.h" -#include "ni_reg.h" -#include "radeon.h" - -static struct radeon_encoder *radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector); - -static int radeon_atom_set_enc_offset(int id) -{ - static const int offsets[] = { EVERGREEN_CRTC0_REGISTER_OFFSET, - EVERGREEN_CRTC1_REGISTER_OFFSET, - EVERGREEN_CRTC2_REGISTER_OFFSET, - EVERGREEN_CRTC3_REGISTER_OFFSET, - EVERGREEN_CRTC4_REGISTER_OFFSET, - EVERGREEN_CRTC5_REGISTER_OFFSET, - 0x13830 - 0x7030 }; - - return offsets[id]; -} - -static int radeon_dp_mst_set_be_cntl(struct radeon_encoder *primary, - struct radeon_encoder_mst *mst_enc, - enum radeon_hpd_id hpd, bool enable) -{ - struct drm_device *dev = primary->base.dev; - struct radeon_device *rdev = dev->dev_private; - uint32_t reg; - int retries = 0; - uint32_t temp; - - reg = RREG32(NI_DIG_BE_CNTL + primary->offset); - - /* set MST mode */ - reg &= ~NI_DIG_FE_DIG_MODE(7); - reg |= NI_DIG_FE_DIG_MODE(NI_DIG_MODE_DP_MST); - - if (enable) - reg |= NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe); - else - reg &= ~NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe); - - reg |= NI_DIG_HPD_SELECT(hpd); - DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DIG_BE_CNTL + primary->offset, reg); - WREG32(NI_DIG_BE_CNTL + primary->offset, reg); - - if (enable) { - uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe); - - do { - temp = RREG32(NI_DIG_FE_CNTL + offset); - } while ((temp & NI_DIG_SYMCLK_FE_ON) && retries++ < 10000); - if (retries == 10000) - DRM_ERROR("timed out waiting for FE %d %d\n", primary->offset, mst_enc->fe); - } - return 0; -} - -static int radeon_dp_mst_set_stream_attrib(struct radeon_encoder *primary, - int stream_number, - int fe, - int slots) -{ - struct drm_device *dev = primary->base.dev; - struct radeon_device *rdev = dev->dev_private; - u32 temp, val; - int retries = 0; - int satreg, satidx; - - satreg = stream_number >> 1; - satidx = stream_number & 1; - - temp = RREG32(NI_DP_MSE_SAT0 + satreg + primary->offset); - - val = NI_DP_MSE_SAT_SLOT_COUNT0(slots) | NI_DP_MSE_SAT_SRC0(fe); - - val <<= (16 * satidx); - - temp &= ~(0xffff << (16 * satidx)); - - temp |= val; - - DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DP_MSE_SAT0 + satreg + primary->offset, temp); - WREG32(NI_DP_MSE_SAT0 + satreg + primary->offset, temp); - - WREG32(NI_DP_MSE_SAT_UPDATE + primary->offset, 1); - - do { - unsigned value1, value2; - udelay(10); - temp = RREG32(NI_DP_MSE_SAT_UPDATE + primary->offset); - - value1 = temp & NI_DP_MSE_SAT_UPDATE_MASK; - value2 = temp & NI_DP_MSE_16_MTP_KEEPOUT; - - if (!value1 && !value2) - break; - } while (retries++ < 50); - - if (retries == 10000) - DRM_ERROR("timed out waitin for SAT update %d\n", primary->offset); - - /* MTP 16 ? */ - return 0; -} - -static int radeon_dp_mst_update_stream_attribs(struct radeon_connector *mst_conn, - struct radeon_encoder *primary) -{ - struct drm_device *dev = mst_conn->base.dev; - struct stream_attribs new_attribs[6]; - int i; - int idx = 0; - struct radeon_connector *radeon_connector; - struct drm_connector *connector; - - memset(new_attribs, 0, sizeof(new_attribs)); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct radeon_encoder *subenc; - struct radeon_encoder_mst *mst_enc; - - radeon_connector = to_radeon_connector(connector); - if (!radeon_connector->is_mst_connector) - continue; - - if (radeon_connector->mst_port != mst_conn) - continue; - - subenc = radeon_connector->mst_encoder; - mst_enc = subenc->enc_priv; - - if (!mst_enc->enc_active) - continue; - - new_attribs[idx].fe = mst_enc->fe; - new_attribs[idx].slots = drm_dp_mst_get_vcpi_slots(&mst_conn->mst_mgr, mst_enc->port); - idx++; - } - - for (i = 0; i < idx; i++) { - if (new_attribs[i].fe != mst_conn->cur_stream_attribs[i].fe || - new_attribs[i].slots != mst_conn->cur_stream_attribs[i].slots) { - radeon_dp_mst_set_stream_attrib(primary, i, new_attribs[i].fe, new_attribs[i].slots); - mst_conn->cur_stream_attribs[i].fe = new_attribs[i].fe; - mst_conn->cur_stream_attribs[i].slots = new_attribs[i].slots; - } - } - - for (i = idx; i < mst_conn->enabled_attribs; i++) { - radeon_dp_mst_set_stream_attrib(primary, i, 0, 0); - mst_conn->cur_stream_attribs[i].fe = 0; - mst_conn->cur_stream_attribs[i].slots = 0; - } - mst_conn->enabled_attribs = idx; - return 0; -} - -static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, s64 avg_time_slots_per_mtp) -{ - struct drm_device *dev = mst->base.dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder_mst *mst_enc = mst->enc_priv; - uint32_t val, temp; - uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe); - int retries = 0; - uint32_t x = drm_fixp2int(avg_time_slots_per_mtp); - uint32_t y = drm_fixp2int_ceil((avg_time_slots_per_mtp - x) << 26); - - val = NI_DP_MSE_RATE_X(x) | NI_DP_MSE_RATE_Y(y); - - WREG32(NI_DP_MSE_RATE_CNTL + offset, val); - - do { - temp = RREG32(NI_DP_MSE_RATE_UPDATE + offset); - udelay(10); - } while ((temp & 0x1) && (retries++ < 10000)); - - if (retries >= 10000) - DRM_ERROR("timed out wait for rate cntl %d\n", mst_enc->fe); - return 0; -} - -static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - struct radeon_connector *master = radeon_connector->mst_port; - struct edid *edid; - int ret = 0; - - edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, radeon_connector->port); - radeon_connector->edid = edid; - DRM_DEBUG_KMS("edid retrieved %p\n", edid); - if (radeon_connector->edid) { - drm_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); - ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); - return ret; - } - drm_connector_update_edid_property(&radeon_connector->base, NULL); - - return ret; -} - -static int radeon_dp_mst_get_modes(struct drm_connector *connector) -{ - return radeon_dp_mst_get_ddc_modes(connector); -} - -static enum drm_mode_status -radeon_dp_mst_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - /* TODO - validate mode against available PBN for link */ - if (mode->clock < 10000) - return MODE_CLOCK_LOW; - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_H_ILLEGAL; - - return MODE_OK; -} - -static struct -drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - - return &radeon_connector->mst_encoder->base; -} - -static int -radeon_dp_mst_detect(struct drm_connector *connector, - struct drm_modeset_acquire_ctx *ctx, - bool force) -{ - struct radeon_connector *radeon_connector = - to_radeon_connector(connector); - struct radeon_connector *master = radeon_connector->mst_port; - - if (drm_connector_is_unregistered(connector)) - return connector_status_disconnected; - - return drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr, - radeon_connector->port); -} - -static const struct drm_connector_helper_funcs radeon_dp_mst_connector_helper_funcs = { - .get_modes = radeon_dp_mst_get_modes, - .mode_valid = radeon_dp_mst_mode_valid, - .best_encoder = radeon_mst_best_encoder, - .detect_ctx = radeon_dp_mst_detect, -}; - -static void -radeon_dp_mst_connector_destroy(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - struct radeon_encoder *radeon_encoder = radeon_connector->mst_encoder; - - drm_encoder_cleanup(&radeon_encoder->base); - kfree(radeon_encoder); - drm_connector_cleanup(connector); - kfree(radeon_connector); -} - -static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = radeon_dp_mst_connector_destroy, -}; - -static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, - const char *pathprop) -{ - struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr); - struct drm_device *dev = master->base.dev; - struct radeon_connector *radeon_connector; - struct drm_connector *connector; - - radeon_connector = kzalloc(sizeof(*radeon_connector), GFP_KERNEL); - if (!radeon_connector) - return NULL; - - radeon_connector->is_mst_connector = true; - connector = &radeon_connector->base; - radeon_connector->port = port; - radeon_connector->mst_port = master; - DRM_DEBUG_KMS("\n"); - - drm_connector_init(dev, connector, &radeon_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); - drm_connector_helper_add(connector, &radeon_dp_mst_connector_helper_funcs); - radeon_connector->mst_encoder = radeon_dp_create_fake_mst_encoder(master); - - drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0); - drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0); - drm_connector_set_path_property(connector, pathprop); - - return connector; -} - -static const struct drm_dp_mst_topology_cbs mst_cbs = { - .add_connector = radeon_dp_add_mst_connector, -}; - -static struct -radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct drm_connector *connector; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - if (!connector->encoder) - continue; - if (!radeon_connector->is_mst_connector) - continue; - - DRM_DEBUG_KMS("checking %p vs %p\n", connector->encoder, encoder); - if (connector->encoder == encoder) - return radeon_connector; - } - return NULL; -} - -void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) -{ - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(radeon_crtc->encoder); - struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv; - struct radeon_connector *radeon_connector = radeon_mst_find_connector(&radeon_encoder->base); - int dp_clock; - struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv; - - if (radeon_connector) { - radeon_connector->pixelclock_for_modeset = mode->clock; - if (radeon_connector->base.display_info.bpc) - radeon_crtc->bpc = radeon_connector->base.display_info.bpc; - else - radeon_crtc->bpc = 8; - } - - DRM_DEBUG_KMS("dp_clock %p %d\n", dig_connector, dig_connector->dp_clock); - dp_clock = dig_connector->dp_clock; - radeon_crtc->ss_enabled = - radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss, - ASIC_INTERNAL_SS_ON_DP, - dp_clock); -} - -static void -radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder *radeon_encoder, *primary; - struct radeon_encoder_mst *mst_enc; - struct radeon_encoder_atom_dig *dig_enc; - struct radeon_connector *radeon_connector; - struct drm_crtc *crtc; - struct radeon_crtc *radeon_crtc; - int slots; - s64 fixed_pbn, fixed_pbn_per_slot, avg_time_slots_per_mtp; - if (!ASIC_IS_DCE5(rdev)) { - DRM_ERROR("got mst dpms on non-DCE5\n"); - return; - } - - radeon_connector = radeon_mst_find_connector(encoder); - if (!radeon_connector) - return; - - radeon_encoder = to_radeon_encoder(encoder); - - mst_enc = radeon_encoder->enc_priv; - - primary = mst_enc->primary; - - dig_enc = primary->enc_priv; - - crtc = encoder->crtc; - DRM_DEBUG_KMS("got connector %d\n", dig_enc->active_mst_links); - - switch (mode) { - case DRM_MODE_DPMS_ON: - dig_enc->active_mst_links++; - - radeon_crtc = to_radeon_crtc(crtc); - - if (dig_enc->active_mst_links == 1) { - mst_enc->fe = dig_enc->dig_encoder; - mst_enc->fe_from_be = true; - atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe); - - atombios_dig_encoder_setup(&primary->base, ATOM_ENCODER_CMD_SETUP, 0); - atombios_dig_transmitter_setup2(&primary->base, ATOM_TRANSMITTER_ACTION_ENABLE, - 0, 0, dig_enc->dig_encoder); - - if (radeon_dp_needs_link_train(mst_enc->connector) || - dig_enc->active_mst_links == 1) { - radeon_dp_link_train(&primary->base, &mst_enc->connector->base); - } - - } else { - mst_enc->fe = radeon_atom_pick_dig_encoder(encoder, radeon_crtc->crtc_id); - if (mst_enc->fe == -1) - DRM_ERROR("failed to get frontend for dig encoder\n"); - mst_enc->fe_from_be = false; - atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe); - } - - DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder, - dig_enc->linkb, radeon_crtc->crtc_id); - - slots = drm_dp_find_vcpi_slots(&radeon_connector->mst_port->mst_mgr, - mst_enc->pbn); - drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr, - radeon_connector->port, - mst_enc->pbn, slots); - drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr, 1); - - radeon_dp_mst_set_be_cntl(primary, mst_enc, - radeon_connector->mst_port->hpd.hpd, true); - - mst_enc->enc_active = true; - radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary); - - fixed_pbn = drm_int2fixp(mst_enc->pbn); - fixed_pbn_per_slot = drm_int2fixp(radeon_connector->mst_port->mst_mgr.pbn_div); - avg_time_slots_per_mtp = drm_fixp_div(fixed_pbn, fixed_pbn_per_slot); - radeon_dp_mst_set_vcp_size(radeon_encoder, avg_time_slots_per_mtp); - - atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0, - mst_enc->fe); - drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr); - - drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr); - - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - DRM_ERROR("DPMS OFF %d\n", dig_enc->active_mst_links); - - if (!mst_enc->enc_active) - return; - - drm_dp_mst_reset_vcpi_slots(&radeon_connector->mst_port->mst_mgr, mst_enc->port); - drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr, 1); - - drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr); - /* and this can also fail */ - drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr); - - drm_dp_mst_deallocate_vcpi(&radeon_connector->mst_port->mst_mgr, mst_enc->port); - - mst_enc->enc_active = false; - radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary); - - radeon_dp_mst_set_be_cntl(primary, mst_enc, - radeon_connector->mst_port->hpd.hpd, false); - atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0, - mst_enc->fe); - - if (!mst_enc->fe_from_be) - radeon_atom_release_dig_encoder(rdev, mst_enc->fe); - - mst_enc->fe_from_be = false; - dig_enc->active_mst_links--; - if (dig_enc->active_mst_links == 0) { - /* drop link */ - } - - break; - } - -} - -static bool radeon_mst_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct radeon_encoder_mst *mst_enc; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_connector_atom_dig *dig_connector; - int bpp = 24; - - mst_enc = radeon_encoder->enc_priv; - - mst_enc->pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp, false); - - mst_enc->primary->active_device = mst_enc->primary->devices & mst_enc->connector->devices; - DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n", - mst_enc->primary->active_device, mst_enc->primary->devices, - mst_enc->connector->devices, mst_enc->primary->base.encoder_type); - - - drm_mode_set_crtcinfo(adjusted_mode, 0); - dig_connector = mst_enc->connector->con_priv; - dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd); - dig_connector->dp_clock = drm_dp_max_link_rate(dig_connector->dpcd); - DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector, - dig_connector->dp_lane_count, dig_connector->dp_clock); - return true; -} - -static void radeon_mst_encoder_prepare(struct drm_encoder *encoder) -{ - struct radeon_connector *radeon_connector; - struct radeon_encoder *radeon_encoder, *primary; - struct radeon_encoder_mst *mst_enc; - struct radeon_encoder_atom_dig *dig_enc; - - radeon_connector = radeon_mst_find_connector(encoder); - if (!radeon_connector) { - DRM_DEBUG_KMS("failed to find connector %p\n", encoder); - return; - } - radeon_encoder = to_radeon_encoder(encoder); - - radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); - - mst_enc = radeon_encoder->enc_priv; - - primary = mst_enc->primary; - - dig_enc = primary->enc_priv; - - mst_enc->port = radeon_connector->port; - - if (dig_enc->dig_encoder == -1) { - dig_enc->dig_encoder = radeon_atom_pick_dig_encoder(&primary->base, -1); - primary->offset = radeon_atom_set_enc_offset(dig_enc->dig_encoder); - atombios_set_mst_encoder_crtc_source(encoder, dig_enc->dig_encoder); - - - } - DRM_DEBUG_KMS("%d %d\n", dig_enc->dig_encoder, primary->offset); -} - -static void -radeon_mst_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - DRM_DEBUG_KMS("\n"); -} - -static void radeon_mst_encoder_commit(struct drm_encoder *encoder) -{ - radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_ON); - DRM_DEBUG_KMS("\n"); -} - -static const struct drm_encoder_helper_funcs radeon_mst_helper_funcs = { - .dpms = radeon_mst_encoder_dpms, - .mode_fixup = radeon_mst_mode_fixup, - .prepare = radeon_mst_encoder_prepare, - .mode_set = radeon_mst_encoder_mode_set, - .commit = radeon_mst_encoder_commit, -}; - -static void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); - kfree(encoder); -} - -static const struct drm_encoder_funcs radeon_dp_mst_enc_funcs = { - .destroy = radeon_dp_mst_encoder_destroy, -}; - -static struct radeon_encoder * -radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector) -{ - struct drm_device *dev = connector->base.dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder *radeon_encoder; - struct radeon_encoder_mst *mst_enc; - struct drm_encoder *encoder; - const struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private; - struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base); - - DRM_DEBUG_KMS("enc master is %p\n", enc_master); - radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL); - if (!radeon_encoder) - return NULL; - - radeon_encoder->enc_priv = kzalloc(sizeof(*mst_enc), GFP_KERNEL); - if (!radeon_encoder->enc_priv) { - kfree(radeon_encoder); - return NULL; - } - encoder = &radeon_encoder->base; - switch (rdev->num_crtc) { - case 1: - encoder->possible_crtcs = 0x1; - break; - case 2: - default: - encoder->possible_crtcs = 0x3; - break; - case 4: - encoder->possible_crtcs = 0xf; - break; - case 6: - encoder->possible_crtcs = 0x3f; - break; - } - - drm_encoder_init(dev, &radeon_encoder->base, &radeon_dp_mst_enc_funcs, - DRM_MODE_ENCODER_DPMST, NULL); - drm_encoder_helper_add(encoder, &radeon_mst_helper_funcs); - - mst_enc = radeon_encoder->enc_priv; - mst_enc->connector = connector; - mst_enc->primary = to_radeon_encoder(enc_master); - radeon_encoder->is_mst_encoder = true; - return radeon_encoder; -} - -int -radeon_dp_mst_init(struct radeon_connector *radeon_connector) -{ - struct drm_device *dev = radeon_connector->base.dev; - int max_link_rate; - - if (!radeon_connector->ddc_bus->has_aux) - return 0; - - if (radeon_connector_is_dp12_capable(&radeon_connector->base)) - max_link_rate = 0x14; - else - max_link_rate = 0x0a; - - radeon_connector->mst_mgr.cbs = &mst_cbs; - return drm_dp_mst_topology_mgr_init(&radeon_connector->mst_mgr, dev, - &radeon_connector->ddc_bus->aux, 16, 6, - 4, drm_dp_bw_code_to_link_rate(max_link_rate), - radeon_connector->base.base.id); -} - -int -radeon_dp_mst_probe(struct radeon_connector *radeon_connector) -{ - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - struct drm_device *dev = radeon_connector->base.dev; - struct radeon_device *rdev = dev->dev_private; - int ret; - u8 msg[1]; - - if (!radeon_mst) - return 0; - - if (!ASIC_IS_DCE5(rdev)) - return 0; - - if (dig_connector->dpcd[DP_DPCD_REV] < 0x12) - return 0; - - ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_MSTM_CAP, msg, - 1); - if (ret) { - if (msg[0] & DP_MST_CAP) { - DRM_DEBUG_KMS("Sink is MST capable\n"); - dig_connector->is_mst = true; - } else { - DRM_DEBUG_KMS("Sink is not MST capable\n"); - dig_connector->is_mst = false; - } - - } - drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr, - dig_connector->is_mst); - return dig_connector->is_mst; -} - -int -radeon_dp_mst_check_status(struct radeon_connector *radeon_connector) -{ - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - int retry; - - if (dig_connector->is_mst) { - u8 esi[16] = { 0 }; - int dret; - int ret = 0; - bool handled; - - dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, - DP_SINK_COUNT_ESI, esi, 8); -go_again: - if (dret == 8) { - DRM_DEBUG_KMS("got esi %3ph\n", esi); - ret = drm_dp_mst_hpd_irq(&radeon_connector->mst_mgr, esi, &handled); - - if (handled) { - for (retry = 0; retry < 3; retry++) { - int wret; - wret = drm_dp_dpcd_write(&radeon_connector->ddc_bus->aux, - DP_SINK_COUNT_ESI + 1, &esi[1], 3); - if (wret == 3) - break; - } - - dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, - DP_SINK_COUNT_ESI, esi, 8); - if (dret == 8) { - DRM_DEBUG_KMS("got esi2 %3ph\n", esi); - goto go_again; - } - } else - ret = 0; - - return ret; - } else { - DRM_DEBUG_KMS("failed to get ESI - device may have failed %d\n", ret); - dig_connector->is_mst = false; - drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr, - dig_connector->is_mst); - /* send a hotplug event */ - } - } - return -EINVAL; -} - -#if defined(CONFIG_DEBUG_FS) - -static int radeon_debugfs_mst_info_show(struct seq_file *m, void *unused) -{ - struct radeon_device *rdev = (struct radeon_device *)m->private; - struct drm_device *dev = rdev->ddev; - struct drm_connector *connector; - struct radeon_connector *radeon_connector; - struct radeon_connector_atom_dig *dig_connector; - int i; - - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) - continue; - - radeon_connector = to_radeon_connector(connector); - dig_connector = radeon_connector->con_priv; - if (radeon_connector->is_mst_connector) - continue; - if (!dig_connector->is_mst) - continue; - drm_dp_mst_dump_topology(m, &radeon_connector->mst_mgr); - - for (i = 0; i < radeon_connector->enabled_attribs; i++) - seq_printf(m, "attrib %d: %d %d\n", i, - radeon_connector->cur_stream_attribs[i].fe, - radeon_connector->cur_stream_attribs[i].slots); - } - drm_modeset_unlock_all(dev); - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(radeon_debugfs_mst_info); -#endif - -void radeon_mst_debugfs_init(struct radeon_device *rdev) -{ -#if defined(CONFIG_DEBUG_FS) - struct dentry *root = rdev->ddev->primary->debugfs_root; - - debugfs_create_file("radeon_mst_info", 0444, root, rdev, - &radeon_debugfs_mst_info_fops); - -#endif -} diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 956c72b5aa33..a28d5ceab628 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -172,7 +172,6 @@ int radeon_use_pflipirq = 2; int radeon_bapm = -1; int radeon_backlight = -1; int radeon_auxch = -1; -int radeon_mst = 0; int radeon_uvd = 1; int radeon_vce = 1; @@ -263,9 +262,6 @@ module_param_named(backlight, radeon_backlight, int, 0444); MODULE_PARM_DESC(auxch, "Use native auxch experimental support (1 = enable, 0 = disable, -1 = auto)"); module_param_named(auxch, radeon_auxch, int, 0444); -MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)"); -module_param_named(mst, radeon_mst, int, 0444); - MODULE_PARM_DESC(uvd, "uvd enable/disable uvd support (1 = enable, 0 = disable)"); module_param_named(uvd, radeon_uvd, int, 0444); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 46549d5179ee..35c535e48b8d 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -244,16 +244,7 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { radeon_connector = to_radeon_connector(connector); - if (radeon_encoder->is_mst_encoder) { - struct radeon_encoder_mst *mst_enc; - - if (!radeon_connector->is_mst_connector) - continue; - - mst_enc = radeon_encoder->enc_priv; - if (mst_enc->connector == radeon_connector->mst_port) - return connector; - } else if (radeon_encoder->active_device & radeon_connector->devices) + if (radeon_encoder->active_device & radeon_connector->devices) return connector; } return NULL; @@ -399,9 +390,6 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_DisplayPort: - if (radeon_connector->is_mst_connector) - return false; - dig_connector = radeon_connector->con_priv; if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 3907785d0798..da2173435edd 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -100,16 +100,8 @@ static void radeon_hotplug_work_func(struct work_struct *work) static void radeon_dp_work_func(struct work_struct *work) { - struct radeon_device *rdev = container_of(work, struct radeon_device, - dp_work); - struct drm_device *dev = rdev->ddev; - struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_connector *connector; - - /* this should take a mutex */ - list_for_each_entry(connector, &mode_config->connector_list, head) - radeon_connector_hotplug(connector); } + /** * radeon_driver_irq_preinstall_kms - drm irq preinstall callback * diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index b34cffc162e2..6a6a73204226 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -31,7 +31,6 @@ #define RADEON_MODE_H #include <drm/display/drm_dp_helper.h> -#include <drm/display/drm_dp_mst_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> #include <drm/drm_encoder.h> @@ -436,24 +435,12 @@ struct radeon_encoder_atom_dig { int panel_mode; struct radeon_afmt *afmt; struct r600_audio_pin *pin; - int active_mst_links; }; struct radeon_encoder_atom_dac { enum radeon_tv_std tv_std; }; -struct radeon_encoder_mst { - int crtc; - struct radeon_encoder *primary; - struct radeon_connector *connector; - struct drm_dp_mst_port *port; - int pbn; - int fe; - bool fe_from_be; - bool enc_active; -}; - struct radeon_encoder { struct drm_encoder base; uint32_t encoder_enum; @@ -475,8 +462,6 @@ struct radeon_encoder { enum radeon_output_csc output_csc; bool can_mst; uint32_t offset; - bool is_mst_encoder; - /* front end for this mst encoder */ }; struct radeon_connector_atom_dig { @@ -487,7 +472,6 @@ struct radeon_connector_atom_dig { int dp_clock; int dp_lane_count; bool edp_on; - bool is_mst; }; struct radeon_gpio_rec { @@ -531,11 +515,6 @@ enum radeon_connector_dither { RADEON_FMT_DITHER_ENABLE = 1, }; -struct stream_attribs { - uint16_t fe; - uint16_t slots; -}; - struct radeon_connector { struct drm_connector base; uint32_t connector_id; @@ -558,14 +537,6 @@ struct radeon_connector { enum radeon_connector_audio audio; enum radeon_connector_dither dither; int pixelclock_for_modeset; - bool is_mst_connector; - struct radeon_connector *mst_port; - struct drm_dp_mst_port *port; - struct drm_dp_mst_topology_mgr mst_mgr; - - struct radeon_encoder *mst_encoder; - struct stream_attribs cur_stream_attribs[6]; - int enabled_attribs; }; #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ @@ -767,8 +738,6 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, extern void atombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe); -extern void atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, - int fe); extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); @@ -986,15 +955,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); -/* mst */ -int radeon_dp_mst_init(struct radeon_connector *radeon_connector); -int radeon_dp_mst_probe(struct radeon_connector *radeon_connector); -int radeon_dp_mst_check_status(struct radeon_connector *radeon_connector); -void radeon_mst_debugfs_init(struct radeon_device *rdev); -void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode); - -void radeon_setup_mst_connector(struct drm_device *dev); - int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx); void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx); #endif From 4d07b0bc403403438d9cf88450506240c5faf92f Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 17 Aug 2022 15:38:46 -0400 Subject: [PATCH 316/396] drm/display/dp_mst: Move all payload info into the atomic state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we've finally gotten rid of the non-atomic MST users leftover in the kernel, we can finally get rid of all of the legacy payload code we have and move as much as possible into the MST atomic state structs. The main purpose of this is to make the MST code a lot less confusing to work on, as there's a lot of duplicated logic that doesn't really need to be here. As well, this should make introducing features like fallback link retraining and DSC support far easier. Since the old payload code was pretty gnarly and there's a Lot of changes here, I expect this might be a bit difficult to review. So to make things as easy as possible for reviewers, I'll sum up how both the old and new code worked here (it took me a while to figure this out too!). The old MST code basically worked by maintaining two different payload tables - proposed_vcpis, and payloads. proposed_vcpis would hold the modified payload we wanted to push to the topology, while payloads held the payload table that was currently programmed in hardware. Modifications to proposed_vcpis would be handled through drm_dp_allocate_vcpi(), drm_dp_mst_deallocate_vcpi(), and drm_dp_mst_reset_vcpi_slots(). Then, they would be pushed via drm_dp_mst_update_payload_step1() and drm_dp_mst_update_payload_step2(). Furthermore, it's important to note how adding and removing VC payloads actually worked with drm_dp_mst_update_payload_step1(). When a VC payload is removed from the VC table, all VC payloads which come after the removed VC payload's slots must have their time slots shifted towards the start of the table. The old code handles this by looping through the entire payload table and recomputing the start slot for every payload in the topology from scratch. While very much overkill, this ends up doing the right thing because we always order the VCPIs for payloads from first to last starting timeslot. It's important to also note that drm_dp_mst_update_payload_step2() isn't actually limited to updating a single payload - the driver can use it to queue up multiple payload changes so that as many of them can be sent as possible before waiting for the ACT. This is -technically- not against spec, but as Wayne Lin has pointed out it's not consistently implemented correctly in hubs - so it might as well be. drm_dp_mst_update_payload_step2() is pretty self explanatory and basically the same between the old and new code, save for the fact we don't have a second step for deleting payloads anymore -and thus rename it to drm_dp_mst_add_payload_step2(). The new payload code stores all of the current payload info within the MST atomic state and computes as much of the state as possible ahead of time. This has the one exception of the starting timeslots for payloads, which can't be determined at atomic check time since the starting time slots will vary depending on what order CRTCs are enabled in the atomic state - which varies from driver to driver. These are still stored in the atomic MST state, but are only copied from the old MST state during atomic commit time. Likewise, this is when new start slots are determined. Adding/removing payloads now works much more closely to how things are described in the spec. When we delete a payload, we loop through the current list of payloads and update the start slots for any payloads whose time slots came after the payload we just deleted. Determining the starting time slots for new payloads being added is done by simply keeping track of where the end of the VC table is in drm_dp_mst_topology_mgr->next_start_slot. Additionally, it's worth noting that we no longer have a single update_payload() function. Instead, we now have drm_dp_mst_add_payload_step1|2() and drm_dp_mst_remove_payload(). As such, it's now left it up to the driver to figure out when to add or remove payloads. The driver already knows when it's disabling/enabling CRTCs, so it also already knows when payloads should be added or removed. Changes since v1: * Refactor around all of the completely dead code changes that are happening in amdgpu for some reason when they really shouldn't even be there in the first place… :\ * Remove mention of sending one ACT per series of payload updates. As Wayne Lin pointed out, there are apparently hubs on the market that don't work correctly with this scheme and require a separate ACT per payload update. * Fix accidental drop of mst_mgr.lock - Wayne Lin * Remove mentions of allowing multiple ACT updates per payload change, mention that this is a result of vendors not consistently supporting this part of the spec and requiring a unique ACT for each payload change. * Get rid of reference to drm_dp_mst_port in DC - turns out I just got myself confused by DC and we don't actually need this. Changes since v2: * Get rid of fix for not sending payload deallocations if ddps=0 and just go back to wayne's fix Signed-off-by: Lyude Paul <lyude@redhat.com> Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Fangzhi Zuo <Jerry.Zuo@amd.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <sean@poorly.run> Acked-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220817193847.557945-18-lyude@redhat.com --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 56 +- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 100 +-- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 84 +- .../amd/display/include/link_service_types.h | 3 + drivers/gpu/drm/display/drm_dp_mst_topology.c | 736 ++++++------------ drivers/gpu/drm/i915/display/intel_dp_mst.c | 64 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 24 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 163 ++-- include/drm/display/drm_dp_mst_helper.h | 177 ++--- 9 files changed, 529 insertions(+), 878 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 789748739d79..9ab01c58bedb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6385,6 +6385,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; + struct drm_dp_mst_topology_state *mst_state; enum dc_color_depth color_depth; int clock, bpp = 0; bool is_y420 = false; @@ -6398,6 +6399,13 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, if (!crtc_state->connectors_changed && !crtc_state->mode_changed) return 0; + mst_state = drm_atomic_get_mst_topology_state(state, mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + if (!mst_state->pbn_div) + mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link); + if (!state->duplicated) { int max_bpc = conn_state->max_requested_bpc; is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) && @@ -6409,11 +6417,10 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, clock = adjusted_mode->clock; dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false); } - dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_time_slots(state, - mst_mgr, - mst_port, - dm_new_connector_state->pbn, - dm_mst_get_pbn_divider(aconnector->dc_link)); + + dm_new_connector_state->vcpi_slots = + drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port, + dm_new_connector_state->pbn); if (dm_new_connector_state->vcpi_slots < 0) { DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots); return dm_new_connector_state->vcpi_slots; @@ -6483,18 +6490,12 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, dm_conn_state->pbn = pbn; dm_conn_state->vcpi_slots = slot_num; - drm_dp_mst_atomic_enable_dsc(state, - aconnector->port, - dm_conn_state->pbn, - 0, + drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn, false); continue; } - vcpi = drm_dp_mst_atomic_enable_dsc(state, - aconnector->port, - pbn, pbn_div, - true); + vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, true); if (vcpi < 0) return vcpi; @@ -9336,8 +9337,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; #if defined(CONFIG_DRM_AMD_DC_DCN) struct dsc_mst_fairness_vars vars[MAX_PIPES]; - struct drm_dp_mst_topology_state *mst_state; - struct drm_dp_mst_topology_mgr *mgr; #endif trace_amdgpu_dm_atomic_check_begin(state); @@ -9576,33 +9575,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) - /* set the slot info for each mst_state based on the link encoding format */ - for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { - struct amdgpu_dm_connector *aconnector; - struct drm_connector *connector; - struct drm_connector_list_iter iter; - u8 link_coding_cap; - - if (!mgr->mst_state ) - continue; - - drm_connector_list_iter_begin(dev, &iter); - drm_for_each_connector_iter(connector, &iter) { - int id = connector->index; - - if (id == mst_state->mgr->conn_base_id) { - aconnector = to_amdgpu_dm_connector(connector); - link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link); - drm_dp_mst_update_slots(mst_state, link_coding_cap); - - break; - } - } - drm_connector_list_iter_end(&iter); - - } -#endif /** * Streams and planes are reset when there are changes that affect * bandwidth. Anything that affects bandwidth needs to go through diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 0177a275b4df..988b9bf34c93 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -27,6 +27,7 @@ #include <linux/acpi.h> #include <linux/i2c.h> +#include <drm/drm_atomic.h> #include <drm/drm_probe_helper.h> #include <drm/amdgpu_drm.h> #include <drm/drm_edid.h> @@ -154,40 +155,27 @@ enum dc_edid_status dm_helpers_parse_edid_caps( } static void -fill_dc_mst_payload_table_from_drm(struct amdgpu_dm_connector *aconnector, - struct dc_dp_mst_stream_allocation_table *proposed_table) +fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state, + struct amdgpu_dm_connector *aconnector, + struct dc_dp_mst_stream_allocation_table *table) { - int i; - struct drm_dp_mst_topology_mgr *mst_mgr = - &aconnector->mst_port->mst_mgr; + struct dc_dp_mst_stream_allocation_table new_table = { 0 }; + struct dc_dp_mst_stream_allocation *sa; + struct drm_dp_mst_atomic_payload *payload; - mutex_lock(&mst_mgr->payload_lock); + /* Fill payload info*/ + list_for_each_entry(payload, &mst_state->payloads, next) { + if (payload->delete) + continue; - proposed_table->stream_count = 0; - - /* number of active streams */ - for (i = 0; i < mst_mgr->max_payloads; i++) { - if (mst_mgr->payloads[i].num_slots == 0) - break; /* end of vcp_id table */ - - ASSERT(mst_mgr->payloads[i].payload_state != - DP_PAYLOAD_DELETE_LOCAL); - - if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL || - mst_mgr->payloads[i].payload_state == - DP_PAYLOAD_REMOTE) { - - struct dc_dp_mst_stream_allocation *sa = - &proposed_table->stream_allocations[ - proposed_table->stream_count]; - - sa->slot_count = mst_mgr->payloads[i].num_slots; - sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi; - proposed_table->stream_count++; - } + sa = &new_table.stream_allocations[new_table.stream_count]; + sa->slot_count = payload->time_slots; + sa->vcp_id = payload->vcpi; + new_table.stream_count++; } - mutex_unlock(&mst_mgr->payload_lock); + /* Overwrite the old table */ + *table = new_table; } void dm_helpers_dp_update_branch_info( @@ -205,11 +193,9 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( bool enable) { struct amdgpu_dm_connector *aconnector; - struct dm_connector_state *dm_conn_state; + struct drm_dp_mst_topology_state *mst_state; + struct drm_dp_mst_atomic_payload *payload; struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_port *mst_port; - bool ret; - u8 link_coding_cap = DP_8b_10b_ENCODING; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; /* Accessing the connector state is required for vcpi_slots allocation @@ -220,40 +206,21 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( if (!aconnector || !aconnector->mst_port) return false; - dm_conn_state = to_dm_connector_state(aconnector->base.state); - mst_mgr = &aconnector->mst_port->mst_mgr; - - if (!mst_mgr->mst_state) - return false; - - mst_port = aconnector->port; - -#if defined(CONFIG_DRM_AMD_DC_DCN) - link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link); -#endif - - if (enable) { - - ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, - dm_conn_state->pbn, - dm_conn_state->vcpi_slots); - if (!ret) - return false; - - } else { - drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port); - } + mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); /* It's OK for this to fail */ - drm_dp_update_payload_part1(mst_mgr, (link_coding_cap == DP_CAP_ANSI_128B132B) ? 0:1); + payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); + if (enable) + drm_dp_add_payload_part1(mst_mgr, mst_state, payload); + else + drm_dp_remove_payload(mst_mgr, mst_state, payload); /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or * AUX message. The sequence is slot 1-63 allocated sequence for each * stream. AMD ASIC stream slot allocation should follow the same * sequence. copy DRM MST allocation to dc */ - - fill_dc_mst_payload_table_from_drm(aconnector, proposed_table); + fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table); return true; } @@ -310,8 +277,9 @@ bool dm_helpers_dp_mst_send_payload_allocation( bool enable) { struct amdgpu_dm_connector *aconnector; + struct drm_dp_mst_topology_state *mst_state; struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_port *mst_port; + struct drm_dp_mst_atomic_payload *payload; enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD; enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD; @@ -320,19 +288,16 @@ bool dm_helpers_dp_mst_send_payload_allocation( if (!aconnector || !aconnector->mst_port) return false; - mst_port = aconnector->port; - mst_mgr = &aconnector->mst_port->mst_mgr; + mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); - if (!mst_mgr->mst_state) - return false; - + payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); if (!enable) { set_flag = MST_CLEAR_ALLOCATED_PAYLOAD; clr_flag = MST_ALLOCATE_NEW_PAYLOAD; } - if (drm_dp_update_payload_part2(mst_mgr)) { + if (enable && drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload)) { amdgpu_dm_set_mst_status(&aconnector->mst_status, set_flag, false); } else { @@ -342,9 +307,6 @@ bool dm_helpers_dp_mst_send_payload_allocation( clr_flag, false); } - if (!enable) - drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port); - return true; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 7a0d6cfa77f5..bd9606307dc7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -597,15 +597,8 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, dc_link_dp_get_max_link_enc_cap(aconnector->dc_link, &max_link_enc_cap); aconnector->mst_mgr.cbs = &dm_mst_cbs; - drm_dp_mst_topology_mgr_init( - &aconnector->mst_mgr, - adev_to_drm(dm->adev), - &aconnector->dm_dp_aux.aux, - 16, - 4, - max_link_enc_cap.lane_count, - drm_dp_bw_code_to_link_rate(max_link_enc_cap.link_rate), - aconnector->connector_id); + drm_dp_mst_topology_mgr_init(&aconnector->mst_mgr, adev_to_drm(dm->adev), + &aconnector->dm_dp_aux.aux, 16, 4, aconnector->connector_id); drm_connector_attach_dp_subconnector_property(&aconnector->base); } @@ -710,6 +703,7 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn) } static bool increase_dsc_bpp(struct drm_atomic_state *state, + struct drm_dp_mst_topology_state *mst_state, struct dc_link *dc_link, struct dsc_mst_fairness_params *params, struct dsc_mst_fairness_vars *vars, @@ -722,12 +716,9 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, int min_initial_slack; int next_index; int remaining_to_increase = 0; - int pbn_per_timeslot; int link_timeslots_used; int fair_pbn_alloc; - pbn_per_timeslot = dm_mst_get_pbn_divider(dc_link); - for (i = 0; i < count; i++) { if (vars[i + k].dsc_enabled) { initial_slack[i] = @@ -758,17 +749,17 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, link_timeslots_used = 0; for (i = 0; i < count; i++) - link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, pbn_per_timeslot); + link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, mst_state->pbn_div); - fair_pbn_alloc = (63 - link_timeslots_used) / remaining_to_increase * pbn_per_timeslot; + fair_pbn_alloc = + (63 - link_timeslots_used) / remaining_to_increase * mst_state->pbn_div; if (initial_slack[next_index] > fair_pbn_alloc) { vars[next_index].pbn += fair_pbn_alloc; if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; if (!drm_dp_mst_atomic_check(state)) { vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn); @@ -777,8 +768,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; } } else { @@ -786,8 +776,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; if (!drm_dp_mst_atomic_check(state)) { vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16; @@ -796,8 +785,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; } } @@ -854,8 +842,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state, if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + vars[next_index].pbn) < 0) return false; if (!drm_dp_mst_atomic_check(state)) { @@ -866,8 +853,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state, if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + vars[next_index].pbn) < 0) return false; } @@ -881,17 +867,27 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, struct dc_state *dc_state, struct dc_link *dc_link, struct dsc_mst_fairness_vars *vars, + struct drm_dp_mst_topology_mgr *mgr, int *link_vars_start_index) { - int i, k; struct dc_stream_state *stream; struct dsc_mst_fairness_params params[MAX_PIPES]; struct amdgpu_dm_connector *aconnector; + struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr); int count = 0; + int i, k; bool debugfs_overwrite = false; memset(params, 0, sizeof(params)); + if (IS_ERR(mst_state)) + return false; + + mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link); +#if defined(CONFIG_DRM_AMD_DC_DCN) + drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link)); +#endif + /* Set up params */ for (i = 0; i < dc_state->stream_count; i++) { struct dc_dsc_policy dsc_policy = {0}; @@ -950,11 +946,8 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; - if (drm_dp_atomic_find_time_slots(state, - params[i].port->mgr, - params[i].port, - vars[i + k].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, + vars[i + k].pbn) < 0) return false; } if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) { @@ -968,21 +961,15 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps); vars[i + k].dsc_enabled = true; vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; - if (drm_dp_atomic_find_time_slots(state, - params[i].port->mgr, - params[i].port, - vars[i + k].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, + params[i].port, vars[i + k].pbn) < 0) return false; } else { vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; - if (drm_dp_atomic_find_time_slots(state, - params[i].port->mgr, - params[i].port, - vars[i + k].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, + params[i].port, vars[i + k].pbn) < 0) return false; } } @@ -990,7 +977,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, return false; /* Optimize degree of compression */ - if (!increase_dsc_bpp(state, dc_link, params, vars, count, k)) + if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k)) return false; if (!try_disable_dsc(state, dc_link, params, vars, count, k)) @@ -1136,8 +1123,9 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, continue; mutex_lock(&aconnector->mst_mgr.lock); - if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, - vars, &link_vars_start_index)) { + if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, + &aconnector->mst_mgr, + &link_vars_start_index)) { mutex_unlock(&aconnector->mst_mgr.lock); return false; } @@ -1195,10 +1183,8 @@ static bool continue; mutex_lock(&aconnector->mst_mgr.lock); - if (!compute_mst_dsc_configs_for_link(state, - dc_state, - stream->link, - vars, + if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, + &aconnector->mst_mgr, &link_vars_start_index)) { mutex_unlock(&aconnector->mst_mgr.lock); return false; diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index f75ed6f8fcb8..d76ab72baf0c 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -251,6 +251,9 @@ union dpcd_training_lane_set { * _ONLY_ be filled out from DM and then passed to DC, do NOT use these for _any_ kind of atomic * state calculations in DM, or you will break something. */ + +struct drm_dp_mst_port; + /* DP MST stream allocation (payload bandwidth number) */ struct dc_dp_mst_stream_allocation { uint8_t vcp_id; diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index c4073d733c59..1de438151cc3 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -68,8 +68,7 @@ static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr, static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port); static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr, - int id, - struct drm_dp_payload *payload); + int id, u8 start_slot, u8 num_slots); static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, @@ -1235,57 +1234,6 @@ build_query_stream_enc_status(struct drm_dp_sideband_msg_tx *msg, u8 stream_id, return 0; } -static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_vcpi *vcpi) -{ - int ret, vcpi_ret; - - mutex_lock(&mgr->payload_lock); - ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1); - if (ret > mgr->max_payloads) { - ret = -EINVAL; - drm_dbg_kms(mgr->dev, "out of payload ids %d\n", ret); - goto out_unlock; - } - - vcpi_ret = find_first_zero_bit(&mgr->vcpi_mask, mgr->max_payloads + 1); - if (vcpi_ret > mgr->max_payloads) { - ret = -EINVAL; - drm_dbg_kms(mgr->dev, "out of vcpi ids %d\n", ret); - goto out_unlock; - } - - set_bit(ret, &mgr->payload_mask); - set_bit(vcpi_ret, &mgr->vcpi_mask); - vcpi->vcpi = vcpi_ret + 1; - mgr->proposed_vcpis[ret - 1] = vcpi; -out_unlock: - mutex_unlock(&mgr->payload_lock); - return ret; -} - -static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr, - int vcpi) -{ - int i; - - if (vcpi == 0) - return; - - mutex_lock(&mgr->payload_lock); - drm_dbg_kms(mgr->dev, "putting payload %d\n", vcpi); - clear_bit(vcpi - 1, &mgr->vcpi_mask); - - for (i = 0; i < mgr->max_payloads; i++) { - if (mgr->proposed_vcpis[i] && - mgr->proposed_vcpis[i]->vcpi == vcpi) { - mgr->proposed_vcpis[i] = NULL; - clear_bit(i + 1, &mgr->payload_mask); - } - } - mutex_unlock(&mgr->payload_lock); -} - static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_sideband_msg_tx *txmsg) { @@ -1738,7 +1686,7 @@ drm_dp_mst_dump_port_topology_history(struct drm_dp_mst_port *port) {} #define save_port_topology_ref(port, type) #endif -static struct drm_dp_mst_atomic_payload * +struct drm_dp_mst_atomic_payload * drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state, struct drm_dp_mst_port *port) { @@ -1750,6 +1698,7 @@ drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state, return NULL; } +EXPORT_SYMBOL(drm_atomic_get_mst_payload_state); static void drm_dp_destroy_mst_branch_device(struct kref *kref) { @@ -3252,6 +3201,8 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, struct drm_dp_query_stream_enc_status_ack_reply *status) { + struct drm_dp_mst_topology_state *state; + struct drm_dp_mst_atomic_payload *payload; struct drm_dp_sideband_msg_tx *txmsg; u8 nonce[7]; int ret; @@ -3268,6 +3219,10 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, get_random_bytes(nonce, sizeof(nonce)); + drm_modeset_lock(&mgr->base.lock, NULL); + state = to_drm_dp_mst_topology_state(mgr->base.state); + payload = drm_atomic_get_mst_payload_state(state, port); + /* * "Source device targets the QUERY_STREAM_ENCRYPTION_STATUS message * transaction at the MST Branch device directly connected to the @@ -3275,7 +3230,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, */ txmsg->dst = mgr->mst_primary; - build_query_stream_enc_status(txmsg, port->vcpi.vcpi, nonce); + build_query_stream_enc_status(txmsg, payload->vcpi, nonce); drm_dp_queue_down_tx(mgr, txmsg); @@ -3292,6 +3247,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, memcpy(status, &txmsg->reply.u.enc_status, sizeof(*status)); out: + drm_modeset_unlock(&mgr->base.lock); drm_dp_mst_topology_put_port(port); out_get_port: kfree(txmsg); @@ -3300,238 +3256,162 @@ out_get_port: EXPORT_SYMBOL(drm_dp_send_query_stream_enc_status); static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr, - int id, - struct drm_dp_payload *payload) + struct drm_dp_mst_atomic_payload *payload) { - int ret; - - ret = drm_dp_dpcd_write_payload(mgr, id, payload); - if (ret < 0) { - payload->payload_state = 0; - return ret; - } - payload->payload_state = DP_PAYLOAD_LOCAL; - return 0; + return drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, + payload->time_slots); } static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, - int id, - struct drm_dp_payload *payload) + struct drm_dp_mst_atomic_payload *payload) { int ret; + struct drm_dp_mst_port *port = drm_dp_mst_topology_get_port_validated(mgr, payload->port); - ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn); - if (ret < 0) - return ret; - payload->payload_state = DP_PAYLOAD_REMOTE; + if (!port) + return -EIO; + + ret = drm_dp_payload_send_msg(mgr, port, payload->vcpi, payload->pbn); + drm_dp_mst_topology_put_port(port); return ret; } static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, - int id, - struct drm_dp_payload *payload) + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_atomic_payload *payload) { drm_dbg_kms(mgr->dev, "\n"); + /* it's okay for these to fail */ - if (port) { - drm_dp_payload_send_msg(mgr, port, id, 0); - } + drm_dp_payload_send_msg(mgr, payload->port, payload->vcpi, 0); + drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, 0); - drm_dp_dpcd_write_payload(mgr, id, payload); - payload->payload_state = DP_PAYLOAD_DELETE_LOCAL; - return 0; -} - -static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr, - int id, - struct drm_dp_payload *payload) -{ - payload->payload_state = 0; return 0; } /** - * drm_dp_update_payload_part1() - Execute payload update part 1 - * @mgr: manager to use. - * @start_slot: this is the cur slot + * drm_dp_add_payload_part1() - Execute payload update part 1 + * @mgr: Manager to use. + * @mst_state: The MST atomic state + * @payload: The payload to write * - * NOTE: start_slot is a temporary workaround for non-atomic drivers, - * this will be removed when non-atomic mst helpers are moved out of the helper + * Determines the starting time slot for the given payload, and programs the VCPI for this payload + * into hardware. After calling this, the driver should generate ACT and payload packets. * - * This iterates over all proposed virtual channels, and tries to - * allocate space in the link for them. For 0->slots transitions, - * this step just writes the VCPI to the MST device. For slots->0 - * transitions, this writes the updated VCPIs and removes the - * remote VC payloads. - * - * after calling this the driver should generate ACT and payload - * packets. + * Returns: 0 on success, error code on failure. In the event that this fails, + * @payload.vc_start_slot will also be set to -1. */ -int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot) +int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_atomic_payload *payload) { - struct drm_dp_payload req_payload; struct drm_dp_mst_port *port; - int i, j; - int cur_slots = start_slot; - bool skip; + int ret; - mutex_lock(&mgr->payload_lock); - for (i = 0; i < mgr->max_payloads; i++) { - struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i]; - struct drm_dp_payload *payload = &mgr->payloads[i]; - bool put_port = false; + port = drm_dp_mst_topology_get_port_validated(mgr, payload->port); + if (!port) + return 0; - /* solve the current payloads - compare to the hw ones - - update the hw view */ - req_payload.start_slot = cur_slots; - if (vcpi) { - port = container_of(vcpi, struct drm_dp_mst_port, - vcpi); + if (mgr->payload_count == 0) + mgr->next_start_slot = mst_state->start_slot; - mutex_lock(&mgr->lock); - skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); - mutex_unlock(&mgr->lock); + payload->vc_start_slot = mgr->next_start_slot; - if (skip) { - drm_dbg_kms(mgr->dev, - "Virtual channel %d is not in current topology\n", - i); - continue; - } - /* Validated ports don't matter if we're releasing - * VCPI - */ - if (vcpi->num_slots) { - port = drm_dp_mst_topology_get_port_validated( - mgr, port); - if (!port) { - if (vcpi->num_slots == payload->num_slots) { - cur_slots += vcpi->num_slots; - payload->start_slot = req_payload.start_slot; - continue; - } else { - drm_dbg_kms(mgr->dev, - "Fail:set payload to invalid sink"); - mutex_unlock(&mgr->payload_lock); - return -EINVAL; - } - } - put_port = true; - } - - req_payload.num_slots = vcpi->num_slots; - req_payload.vcpi = vcpi->vcpi; - } else { - port = NULL; - req_payload.num_slots = 0; - } - - payload->start_slot = req_payload.start_slot; - /* work out what is required to happen with this payload */ - if (payload->num_slots != req_payload.num_slots) { - - /* need to push an update for this payload */ - if (req_payload.num_slots) { - drm_dp_create_payload_step1(mgr, vcpi->vcpi, - &req_payload); - payload->num_slots = req_payload.num_slots; - payload->vcpi = req_payload.vcpi; - - } else if (payload->num_slots) { - payload->num_slots = 0; - drm_dp_destroy_payload_step1(mgr, port, - payload->vcpi, - payload); - req_payload.payload_state = - payload->payload_state; - payload->start_slot = 0; - } - payload->payload_state = req_payload.payload_state; - } - cur_slots += req_payload.num_slots; - - if (put_port) - drm_dp_mst_topology_put_port(port); + ret = drm_dp_create_payload_step1(mgr, payload); + drm_dp_mst_topology_put_port(port); + if (ret < 0) { + drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n", + payload->port, ret); + payload->vc_start_slot = -1; + return ret; } - for (i = 0; i < mgr->max_payloads; /* do nothing */) { - if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) { - i++; - continue; - } - - drm_dbg_kms(mgr->dev, "removing payload %d\n", i); - for (j = i; j < mgr->max_payloads - 1; j++) { - mgr->payloads[j] = mgr->payloads[j + 1]; - mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1]; - - if (mgr->proposed_vcpis[j] && - mgr->proposed_vcpis[j]->num_slots) { - set_bit(j + 1, &mgr->payload_mask); - } else { - clear_bit(j + 1, &mgr->payload_mask); - } - } - - memset(&mgr->payloads[mgr->max_payloads - 1], 0, - sizeof(struct drm_dp_payload)); - mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL; - clear_bit(mgr->max_payloads, &mgr->payload_mask); - } - mutex_unlock(&mgr->payload_lock); + mgr->payload_count++; + mgr->next_start_slot += payload->time_slots; return 0; } -EXPORT_SYMBOL(drm_dp_update_payload_part1); +EXPORT_SYMBOL(drm_dp_add_payload_part1); /** - * drm_dp_update_payload_part2() - Execute payload update part 2 - * @mgr: manager to use. + * drm_dp_remove_payload() - Remove an MST payload + * @mgr: Manager to use. + * @mst_state: The MST atomic state + * @payload: The payload to write * - * This iterates over all proposed virtual channels, and tries to - * allocate space in the link for them. For 0->slots transitions, - * this step writes the remote VC payload commands. For slots->0 - * this just resets some internal state. + * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates + * the starting time slots of all other payloads which would have been shifted towards the start of + * the VC table as a result. After calling this, the driver should generate ACT and payload packets. */ -int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) +void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_atomic_payload *payload) +{ + struct drm_dp_mst_atomic_payload *pos; + bool send_remove = false; + + /* We failed to make the payload, so nothing to do */ + if (payload->vc_start_slot == -1) + return; + + mutex_lock(&mgr->lock); + send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary); + mutex_unlock(&mgr->lock); + + if (send_remove) + drm_dp_destroy_payload_step1(mgr, mst_state, payload); + else + drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n", + payload->vcpi); + + list_for_each_entry(pos, &mst_state->payloads, next) { + if (pos != payload && pos->vc_start_slot > payload->vc_start_slot) + pos->vc_start_slot -= payload->time_slots; + } + payload->vc_start_slot = -1; + + mgr->payload_count--; + mgr->next_start_slot -= payload->time_slots; +} +EXPORT_SYMBOL(drm_dp_remove_payload); + +/** + * drm_dp_add_payload_part2() - Execute payload update part 2 + * @mgr: Manager to use. + * @state: The global atomic state + * @payload: The payload to update + * + * If @payload was successfully assigned a starting time slot by drm_dp_add_payload_part1(), this + * function will send the sideband messages to finish allocating this payload. + * + * Returns: 0 on success, negative error code on failure. + */ +int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr, + struct drm_atomic_state *state, + struct drm_dp_mst_atomic_payload *payload) { - struct drm_dp_mst_port *port; - int i; int ret = 0; - bool skip; - mutex_lock(&mgr->payload_lock); - for (i = 0; i < mgr->max_payloads; i++) { - - if (!mgr->proposed_vcpis[i]) - continue; - - port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); - - mutex_lock(&mgr->lock); - skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); - mutex_unlock(&mgr->lock); - - if (skip) - continue; - - drm_dbg_kms(mgr->dev, "payload %d %d\n", i, mgr->payloads[i].payload_state); - if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) { - ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]); - } else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) { - ret = drm_dp_destroy_payload_step2(mgr, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]); - } - if (ret) { - mutex_unlock(&mgr->payload_lock); - return ret; - } + /* Skip failed payloads */ + if (payload->vc_start_slot == -1) { + drm_dbg_kms(state->dev, "Part 1 of payload creation for %s failed, skipping part 2\n", + payload->port->connector->name); + return -EIO; } - mutex_unlock(&mgr->payload_lock); - return 0; + + ret = drm_dp_create_payload_step2(mgr, payload); + if (ret < 0) { + if (!payload->delete) + drm_err(mgr->dev, "Step 2 of creating MST payload for %p failed: %d\n", + payload->port, ret); + else + drm_dbg_kms(mgr->dev, "Step 2 of removing MST payload for %p failed: %d\n", + payload->port, ret); + } + + return ret; } -EXPORT_SYMBOL(drm_dp_update_payload_part2); +EXPORT_SYMBOL(drm_dp_add_payload_part2); static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, @@ -3711,7 +3591,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms int ret = 0; struct drm_dp_mst_branch *mstb = NULL; - mutex_lock(&mgr->payload_lock); mutex_lock(&mgr->lock); if (mst_state == mgr->mst_state) goto out_unlock; @@ -3719,10 +3598,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms mgr->mst_state = mst_state; /* set the device into MST mode */ if (mst_state) { - struct drm_dp_payload reset_pay; - int lane_count; - int link_rate; - WARN_ON(mgr->mst_primary); /* get dpcd info */ @@ -3733,16 +3608,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms goto out_unlock; } - lane_count = min_t(int, mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK, mgr->max_lane_count); - link_rate = min_t(int, drm_dp_bw_code_to_link_rate(mgr->dpcd[1]), mgr->max_link_rate); - mgr->pbn_div = drm_dp_get_vc_payload_bw(mgr, - link_rate, - lane_count); - if (mgr->pbn_div == 0) { - ret = -EINVAL; - goto out_unlock; - } - /* add initial branch device at LCT 1 */ mstb = drm_dp_add_mst_branch_device(1, NULL); if (mstb == NULL) { @@ -3762,9 +3627,8 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms if (ret < 0) goto out_unlock; - reset_pay.start_slot = 0; - reset_pay.num_slots = 0x3f; - drm_dp_dpcd_write_payload(mgr, 0, &reset_pay); + /* Write reset payload */ + drm_dp_dpcd_write_payload(mgr, 0, 0, 0x3f); queue_work(system_long_wq, &mgr->work); @@ -3776,19 +3640,11 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms /* this can fail if the device is gone */ drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0); ret = 0; - memset(mgr->payloads, 0, - mgr->max_payloads * sizeof(mgr->payloads[0])); - memset(mgr->proposed_vcpis, 0, - mgr->max_payloads * sizeof(mgr->proposed_vcpis[0])); - mgr->payload_mask = 0; - set_bit(0, &mgr->payload_mask); - mgr->vcpi_mask = 0; mgr->payload_id_table_cleared = false; } out_unlock: mutex_unlock(&mgr->lock); - mutex_unlock(&mgr->payload_lock); if (mstb) drm_dp_mst_topology_put_mstb(mstb); return ret; @@ -4307,62 +4163,18 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ } EXPORT_SYMBOL(drm_dp_mst_get_edid); -/** - * drm_dp_find_vcpi_slots() - Find time slots for this PBN value - * @mgr: manager to use - * @pbn: payload bandwidth to convert into slots. - * - * Calculate the number of time slots that will be required for the given PBN - * value. This function is deprecated, and should not be used in atomic - * drivers. - * - * RETURNS: - * The total slots required for this port, or error. - */ -int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, - int pbn) -{ - int num_slots; - - num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div); - - /* max. time slots - one slot for MTP header */ - if (num_slots > 63) - return -ENOSPC; - return num_slots; -} -EXPORT_SYMBOL(drm_dp_find_vcpi_slots); - -static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_vcpi *vcpi, int pbn, int slots) -{ - int ret; - - vcpi->pbn = pbn; - vcpi->aligned_pbn = slots * mgr->pbn_div; - vcpi->num_slots = slots; - - ret = drm_dp_mst_assign_payload_id(mgr, vcpi); - if (ret < 0) - return ret; - return 0; -} - /** * drm_dp_atomic_find_time_slots() - Find and add time slots to the state * @state: global atomic state * @mgr: MST topology manager for the port * @port: port to find time slots for * @pbn: bandwidth required for the mode in PBN - * @pbn_div: divider for DSC mode that takes FEC into account * - * Allocates time slots to @port, replacing any previous timeslot allocations it - * may have had. Any atomic drivers which support MST must call this function - * in their &drm_encoder_helper_funcs.atomic_check() callback to change the - * current timeslot allocation for the new state, but only when - * &drm_crtc_state.mode_changed or &drm_crtc_state.connectors_changed is set - * to ensure compatibility with userspace applications that still use the - * legacy modesetting UAPI. + * Allocates time slots to @port, replacing any previous time slot allocations it may + * have had. Any atomic drivers which support MST must call this function in + * their &drm_encoder_helper_funcs.atomic_check() callback unconditionally to + * change the current time slot allocation for the new state, and ensure the MST + * atomic state is added whenever the state of payloads in the topology changes. * * Allocations set by this function are not checked against the bandwidth * restraints of @mgr until the driver calls drm_dp_mst_atomic_check(). @@ -4381,8 +4193,7 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, */ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn, - int pbn_div) + struct drm_dp_mst_port *port, int pbn) { struct drm_dp_mst_topology_state *topology_state; struct drm_dp_mst_atomic_payload *payload = NULL; @@ -4415,10 +4226,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, } } - if (pbn_div <= 0) - pbn_div = mgr->pbn_div; - - req_slots = DIV_ROUND_UP(pbn, pbn_div); + req_slots = DIV_ROUND_UP(pbn, topology_state->pbn_div); drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] TU %d -> %d\n", port->connector->base.id, port->connector->name, @@ -4427,7 +4235,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, port->connector->base.id, port->connector->name, port, prev_bw, pbn); - /* Add the new allocation to the state */ + /* Add the new allocation to the state, note the VCPI isn't assigned until the end */ if (!payload) { payload = kzalloc(sizeof(*payload), GFP_KERNEL); if (!payload) @@ -4435,6 +4243,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, drm_dp_mst_get_port_malloc(port); payload->port = port; + payload->vc_start_slot = -1; list_add(&payload->next, &topology_state->payloads); } payload->time_slots = req_slots; @@ -4451,10 +4260,12 @@ EXPORT_SYMBOL(drm_dp_atomic_find_time_slots); * @port: The port to release the time slots from * * Releases any time slots that have been allocated to a port in the atomic - * state. Any atomic drivers which support MST must call this function in - * their &drm_connector_helper_funcs.atomic_check() callback when the - * connector will no longer have VCPI allocated (e.g. because its CRTC was - * removed) when it had VCPI allocated in the previous atomic state. + * state. Any atomic drivers which support MST must call this function + * unconditionally in their &drm_connector_helper_funcs.atomic_check() callback. + * This helper will check whether time slots would be released by the new state and + * respond accordingly, along with ensuring the MST state is always added to the + * atomic state whenever a new state would modify the state of payloads on the + * topology. * * It is OK to call this even if @port has been removed from the system. * Additionally, it is OK to call this function multiple times on the same @@ -4516,6 +4327,7 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, drm_dp_mst_put_port_malloc(port); payload->pbn = 0; payload->delete = true; + topology_state->payload_mask &= ~BIT(payload->vcpi - 1); } return 0; @@ -4566,7 +4378,8 @@ int drm_dp_mst_atomic_setup_commit(struct drm_atomic_state *state) EXPORT_SYMBOL(drm_dp_mst_atomic_setup_commit); /** - * drm_dp_mst_atomic_wait_for_dependencies() - Wait for all pending commits on MST topologies + * drm_dp_mst_atomic_wait_for_dependencies() - Wait for all pending commits on MST topologies, + * prepare new MST state for commit * @state: global atomic state * * Goes through any MST topologies in this atomic state, and waits for any pending commits which @@ -4584,17 +4397,30 @@ EXPORT_SYMBOL(drm_dp_mst_atomic_setup_commit); */ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state) { - struct drm_dp_mst_topology_state *old_mst_state; + struct drm_dp_mst_topology_state *old_mst_state, *new_mst_state; struct drm_dp_mst_topology_mgr *mgr; + struct drm_dp_mst_atomic_payload *old_payload, *new_payload; int i, j, ret; - for_each_old_mst_mgr_in_state(state, mgr, old_mst_state, i) { + for_each_oldnew_mst_mgr_in_state(state, mgr, old_mst_state, new_mst_state, i) { for (j = 0; j < old_mst_state->num_commit_deps; j++) { ret = drm_crtc_commit_wait(old_mst_state->commit_deps[j]); if (ret < 0) drm_err(state->dev, "Failed to wait for %s: %d\n", old_mst_state->commit_deps[j]->crtc->name, ret); } + + /* Now that previous state is committed, it's safe to copy over the start slot + * assignments + */ + list_for_each_entry(old_payload, &old_mst_state->payloads, next) { + if (old_payload->delete) + continue; + + new_payload = drm_atomic_get_mst_payload_state(new_mst_state, + old_payload->port); + new_payload->vc_start_slot = old_payload->vc_start_slot; + } } } EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies); @@ -4679,119 +4505,8 @@ void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_ } EXPORT_SYMBOL(drm_dp_mst_update_slots); -/** - * drm_dp_mst_allocate_vcpi() - Allocate a virtual channel - * @mgr: manager for this port - * @port: port to allocate a virtual channel for. - * @pbn: payload bandwidth number to request - * @slots: returned number of slots for this PBN. - */ -bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn, int slots) -{ - int ret; - - if (slots < 0) - return false; - - port = drm_dp_mst_topology_get_port_validated(mgr, port); - if (!port) - return false; - - if (port->vcpi.vcpi > 0) { - drm_dbg_kms(mgr->dev, - "payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", - port->vcpi.vcpi, port->vcpi.pbn, pbn); - if (pbn == port->vcpi.pbn) { - drm_dp_mst_topology_put_port(port); - return true; - } - } - - ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots); - if (ret) { - drm_dbg_kms(mgr->dev, "failed to init time slots=%d ret=%d\n", - DIV_ROUND_UP(pbn, mgr->pbn_div), ret); - drm_dp_mst_topology_put_port(port); - goto out; - } - drm_dbg_kms(mgr->dev, "initing vcpi for pbn=%d slots=%d\n", pbn, port->vcpi.num_slots); - - /* Keep port allocated until its payload has been removed */ - drm_dp_mst_get_port_malloc(port); - drm_dp_mst_topology_put_port(port); - return true; -out: - return false; -} -EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi); - -int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) -{ - int slots = 0; - - port = drm_dp_mst_topology_get_port_validated(mgr, port); - if (!port) - return slots; - - slots = port->vcpi.num_slots; - drm_dp_mst_topology_put_port(port); - return slots; -} -EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots); - -/** - * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI - * @mgr: manager for this port - * @port: unverified pointer to a port. - * - * This just resets the number of slots for the ports VCPI for later programming. - */ -void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) -{ - /* - * A port with VCPI will remain allocated until its VCPI is - * released, no verified ref needed - */ - - port->vcpi.num_slots = 0; -} -EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); - -/** - * drm_dp_mst_deallocate_vcpi() - deallocate a VCPI - * @mgr: manager for this port - * @port: port to deallocate vcpi for - * - * This can be called unconditionally, regardless of whether - * drm_dp_mst_allocate_vcpi() succeeded or not. - */ -void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port) -{ - bool skip; - - if (!port->vcpi.vcpi) - return; - - mutex_lock(&mgr->lock); - skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); - mutex_unlock(&mgr->lock); - - if (skip) - return; - - drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); - port->vcpi.num_slots = 0; - port->vcpi.pbn = 0; - port->vcpi.aligned_pbn = 0; - port->vcpi.vcpi = 0; - drm_dp_mst_put_port_malloc(port); -} -EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi); - static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr, - int id, struct drm_dp_payload *payload) + int id, u8 start_slot, u8 num_slots) { u8 payload_alloc[3], status; int ret; @@ -4801,8 +4516,8 @@ static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr, DP_PAYLOAD_TABLE_UPDATED); payload_alloc[0] = id; - payload_alloc[1] = payload->start_slot; - payload_alloc[2] = payload->num_slots; + payload_alloc[1] = start_slot; + payload_alloc[2] = num_slots; ret = drm_dp_dpcd_write(mgr->aux, DP_PAYLOAD_ALLOCATE_SET, payload_alloc, 3); if (ret != 3) { @@ -5017,8 +4732,9 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr, void drm_dp_mst_dump_topology(struct seq_file *m, struct drm_dp_mst_topology_mgr *mgr) { - int i; - struct drm_dp_mst_port *port; + struct drm_dp_mst_topology_state *state; + struct drm_dp_mst_atomic_payload *payload; + int i, ret; mutex_lock(&mgr->lock); if (mgr->mst_primary) @@ -5027,36 +4743,35 @@ void drm_dp_mst_dump_topology(struct seq_file *m, /* dump VCPIs */ mutex_unlock(&mgr->lock); - mutex_lock(&mgr->payload_lock); - seq_printf(m, "\n*** VCPI Info ***\n"); - seq_printf(m, "payload_mask: %lx, vcpi_mask: %lx, max_payloads: %d\n", mgr->payload_mask, mgr->vcpi_mask, mgr->max_payloads); + ret = drm_modeset_lock_single_interruptible(&mgr->base.lock); + if (ret < 0) + return; - seq_printf(m, "\n| idx | port # | vcp_id | # slots | sink name |\n"); + state = to_drm_dp_mst_topology_state(mgr->base.state); + seq_printf(m, "\n*** Atomic state info ***\n"); + seq_printf(m, "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n", + state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div); + + seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc | sink name |\n"); for (i = 0; i < mgr->max_payloads; i++) { - if (mgr->proposed_vcpis[i]) { + list_for_each_entry(payload, &state->payloads, next) { char name[14]; - port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); - fetch_monitor_name(mgr, port, name, sizeof(name)); - seq_printf(m, "%10d%10d%10d%10d%20s\n", + if (payload->vcpi != i || payload->delete) + continue; + + fetch_monitor_name(mgr, payload->port, name, sizeof(name)); + seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n", i, - port->port_num, - port->vcpi.vcpi, - port->vcpi.num_slots, + payload->port->port_num, + payload->vcpi, + payload->vc_start_slot, + payload->vc_start_slot + payload->time_slots - 1, + payload->pbn, + payload->dsc_enabled ? "Y" : "N", (*name != 0) ? name : "Unknown"); - } else - seq_printf(m, "%6d - Unused\n", i); + } } - seq_printf(m, "\n*** Payload Info ***\n"); - seq_printf(m, "| idx | state | start slot | # slots |\n"); - for (i = 0; i < mgr->max_payloads; i++) { - seq_printf(m, "%10d%10d%15d%10d\n", - i, - mgr->payloads[i].payload_state, - mgr->payloads[i].start_slot, - mgr->payloads[i].num_slots); - } - mutex_unlock(&mgr->payload_lock); seq_printf(m, "\n*** DPCD Info ***\n"); mutex_lock(&mgr->lock); @@ -5102,7 +4817,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m, out: mutex_unlock(&mgr->lock); - + drm_modeset_unlock(&mgr->base.lock); } EXPORT_SYMBOL(drm_dp_mst_dump_topology); @@ -5423,9 +5138,22 @@ drm_dp_mst_atomic_check_payload_alloc_limits(struct drm_dp_mst_topology_mgr *mgr mgr, mst_state, mgr->max_payloads); return -EINVAL; } + + /* Assign a VCPI */ + if (!payload->vcpi) { + payload->vcpi = ffz(mst_state->payload_mask) + 1; + drm_dbg_atomic(mgr->dev, "[MST PORT:%p] assigned VCPI #%d\n", + payload->port, payload->vcpi); + mst_state->payload_mask |= BIT(payload->vcpi - 1); + } } - drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU avail=%d used=%d\n", - mgr, mst_state, avail_slots, mst_state->total_avail_slots - avail_slots); + + if (!payload_count) + mst_state->pbn_div = 0; + + drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU pbn_div=%d avail=%d used=%d\n", + mgr, mst_state, mst_state->pbn_div, avail_slots, + mst_state->total_avail_slots - avail_slots); return 0; } @@ -5496,7 +5224,6 @@ EXPORT_SYMBOL(drm_dp_mst_add_affected_dsc_crtcs); * @state: Pointer to the new drm_atomic_state * @port: Pointer to the affected MST Port * @pbn: Newly recalculated bw required for link with DSC enabled - * @pbn_div: Divider to calculate correct number of pbn per slot * @enable: Boolean flag to enable or disable DSC on the port * * This function enables DSC on the given Port @@ -5507,8 +5234,7 @@ EXPORT_SYMBOL(drm_dp_mst_add_affected_dsc_crtcs); */ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, struct drm_dp_mst_port *port, - int pbn, int pbn_div, - bool enable) + int pbn, bool enable) { struct drm_dp_mst_topology_state *mst_state; struct drm_dp_mst_atomic_payload *payload; @@ -5534,7 +5260,7 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, } if (enable) { - time_slots = drm_dp_atomic_find_time_slots(state, port->mgr, port, pbn, pbn_div); + time_slots = drm_dp_atomic_find_time_slots(state, port->mgr, port, pbn); drm_dbg_atomic(state->dev, "[MST PORT:%p] Enabling DSC flag, reallocating %d time slots on the port\n", port, time_slots); @@ -5547,6 +5273,7 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, return time_slots; } EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc); + /** * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an * atomic update is valid @@ -5604,7 +5331,6 @@ EXPORT_SYMBOL(drm_dp_mst_topology_state_funcs); /** * drm_atomic_get_mst_topology_state: get MST topology state - * * @state: global atomic state * @mgr: MST topology manager, also the private object in this case * @@ -5623,6 +5349,31 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a } EXPORT_SYMBOL(drm_atomic_get_mst_topology_state); +/** + * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any + * @state: global atomic state + * @mgr: MST topology manager, also the private object in this case + * + * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic + * state vtable so that the private object state returned is that of a MST + * topology object. + * + * Returns: + * + * The MST topology state, or NULL if there's no topology state for this MST mgr + * in the global atomic state + */ +struct drm_dp_mst_topology_state * +drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr *mgr) +{ + struct drm_private_state *priv_state = + drm_atomic_get_new_private_obj_state(state, &mgr->base); + + return priv_state ? to_dp_mst_topology_state(priv_state) : NULL; +} +EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state); + /** * drm_dp_mst_topology_mgr_init - initialise a topology manager * @mgr: manager struct to initialise @@ -5630,8 +5381,6 @@ EXPORT_SYMBOL(drm_atomic_get_mst_topology_state); * @aux: DP helper aux channel to talk to this device * @max_dpcd_transaction_bytes: hw specific DPCD transaction limit * @max_payloads: maximum number of payloads this GPU can source - * @max_lane_count: maximum number of lanes this GPU supports - * @max_link_rate: maximum link rate per lane this GPU supports in kHz * @conn_base_id: the connector object ID the MST device is connected to. * * Return 0 for success, or negative error code on failure @@ -5639,14 +5388,12 @@ EXPORT_SYMBOL(drm_atomic_get_mst_topology_state); int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, struct drm_device *dev, struct drm_dp_aux *aux, int max_dpcd_transaction_bytes, int max_payloads, - int max_lane_count, int max_link_rate, int conn_base_id) { struct drm_dp_mst_topology_state *mst_state; mutex_init(&mgr->lock); mutex_init(&mgr->qlock); - mutex_init(&mgr->payload_lock); mutex_init(&mgr->delayed_destroy_lock); mutex_init(&mgr->up_req_lock); mutex_init(&mgr->probe_lock); @@ -5676,19 +5423,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, mgr->aux = aux; mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes; mgr->max_payloads = max_payloads; - mgr->max_lane_count = max_lane_count; - mgr->max_link_rate = max_link_rate; mgr->conn_base_id = conn_base_id; - if (max_payloads + 1 > sizeof(mgr->payload_mask) * 8 || - max_payloads + 1 > sizeof(mgr->vcpi_mask) * 8) - return -EINVAL; - mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL); - if (!mgr->payloads) - return -ENOMEM; - mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL); - if (!mgr->proposed_vcpis) - return -ENOMEM; - set_bit(0, &mgr->payload_mask); mst_state = kzalloc(sizeof(*mst_state), GFP_KERNEL); if (mst_state == NULL) @@ -5721,19 +5456,12 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) destroy_workqueue(mgr->delayed_destroy_wq); mgr->delayed_destroy_wq = NULL; } - mutex_lock(&mgr->payload_lock); - kfree(mgr->payloads); - mgr->payloads = NULL; - kfree(mgr->proposed_vcpis); - mgr->proposed_vcpis = NULL; - mutex_unlock(&mgr->payload_lock); mgr->dev = NULL; mgr->aux = NULL; drm_atomic_private_obj_fini(&mgr->base); mgr->funcs = NULL; mutex_destroy(&mgr->delayed_destroy_lock); - mutex_destroy(&mgr->payload_lock); mutex_destroy(&mgr->qlock); mutex_destroy(&mgr->lock); mutex_destroy(&mgr->up_req_lock); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 1b067cd73261..13abe2b2170e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -52,6 +52,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, struct drm_atomic_state *state = crtc_state->uapi.state; struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); struct intel_dp *intel_dp = &intel_mst->primary->dp; + struct drm_dp_mst_topology_state *mst_state; struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -60,22 +61,28 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, bool constant_n = drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_CONSTANT_N); int bpp, slots = -EINVAL; + mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + crtc_state->lane_count = limits->max_lane_count; crtc_state->port_clock = limits->max_rate; + // TODO: Handle pbn_div changes by adding a new MST helper + if (!mst_state->pbn_div) { + mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr, + limits->max_rate, + limits->max_lane_count); + } + for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { crtc_state->pipe_bpp = bpp; crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, crtc_state->pipe_bpp, false); - slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, - connector->port, - crtc_state->pbn, - drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr, - crtc_state->port_clock, - crtc_state->lane_count)); + connector->port, crtc_state->pbn); if (slots == -EDEADLK) return slots; if (slots >= 0) @@ -360,21 +367,17 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, struct intel_dp *intel_dp = &dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr); struct drm_i915_private *i915 = to_i915(connector->base.dev); - int start_slot = intel_dp_is_uhbr(old_crtc_state) ? 0 : 1; - int ret; drm_dbg_kms(&i915->drm, "active links %d\n", intel_dp->active_mst_links); intel_hdcp_disable(intel_mst->connector); - drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port); - - ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr, start_slot); - if (ret) { - drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret); - } + drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state, + drm_atomic_get_mst_payload_state(mst_state, connector->port)); intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); } @@ -402,8 +405,6 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, intel_disable_transcoder(old_crtc_state); - drm_dp_update_payload_part2(&intel_dp->mst_mgr); - clear_act_sent(encoder, old_crtc_state); intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder), @@ -411,8 +412,6 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, wait_for_act_sent(encoder, old_crtc_state); - drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port); - intel_ddi_disable_transcoder_func(old_crtc_state); if (DISPLAY_VER(dev_priv) >= 9) @@ -479,7 +478,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_connector *connector = to_intel_connector(conn_state->connector); - int start_slot = intel_dp_is_uhbr(pipe_config) ? 0 : 1; + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr); int ret; bool first_mst_stream; @@ -505,16 +505,13 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, dig_port->base.pre_enable(state, &dig_port->base, pipe_config, NULL); - ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, - connector->port, - pipe_config->pbn, - pipe_config->dp_m_n.tu); - if (!ret) - drm_err(&dev_priv->drm, "failed to allocate vcpi\n"); - intel_dp->active_mst_links++; - ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr, start_slot); + ret = drm_dp_add_payload_part1(&intel_dp->mst_mgr, mst_state, + drm_atomic_get_mst_payload_state(mst_state, connector->port)); + if (ret < 0) + drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n", + connector->base.name, ret); /* * Before Gen 12 this is not done as part of @@ -537,7 +534,10 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); struct intel_digital_port *dig_port = intel_mst->primary; struct intel_dp *intel_dp = &dig_port->dp; + struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr); enum transcoder trans = pipe_config->cpu_transcoder; drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder); @@ -565,7 +565,8 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, wait_for_act_sent(encoder, pipe_config); - drm_dp_update_payload_part2(&intel_dp->mst_mgr); + drm_dp_add_payload_part2(&intel_dp->mst_mgr, &state->base, + drm_atomic_get_mst_payload_state(mst_state, connector->port)); if (DISPLAY_VER(dev_priv) >= 12 && pipe_config->fec_enable) intel_de_rmw(dev_priv, CHICKEN_TRANS(trans), 0, @@ -949,8 +950,6 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id) struct intel_dp *intel_dp = &dig_port->dp; enum port port = dig_port->base.port; int ret; - int max_source_rate = - intel_dp->source_rates[intel_dp->num_source_rates - 1]; if (!HAS_DP_MST(i915) || intel_dp_is_edp(intel_dp)) return 0; @@ -966,10 +965,7 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id) /* create encoders */ intel_dp_create_fake_mst_encoders(dig_port); ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm, - &intel_dp->aux, 16, 3, - dig_port->max_lanes, - max_source_rate, - conn_base_id); + &intel_dp->aux, 16, 3, conn_base_id); if (ret) { intel_dp->mst_mgr.cbs = NULL; return ret; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 8ea66a2e1b09..7dbc9f0bb24f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,8 +30,30 @@ static int intel_conn_to_vcpi(struct intel_connector *connector) { + struct drm_dp_mst_topology_mgr *mgr; + struct drm_dp_mst_atomic_payload *payload; + struct drm_dp_mst_topology_state *mst_state; + int vcpi = 0; + /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */ - return connector->port ? connector->port->vcpi.vcpi : 0; + if (!connector->port) + return 0; + mgr = connector->port->mgr; + + drm_modeset_lock(&mgr->base.lock, NULL); + mst_state = to_drm_dp_mst_topology_state(mgr->base.state); + payload = drm_atomic_get_mst_payload_state(mst_state, connector->port); + if (drm_WARN_ON(mgr->dev, !payload)) + goto out; + + vcpi = payload->vcpi; + if (drm_WARN_ON(mgr->dev, vcpi < 0)) { + vcpi = 0; + goto out; + } +out: + drm_modeset_unlock(&mgr->base.lock); + return vcpi; } /* diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 7e9a0b50bb42..33c97d510999 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -932,6 +932,7 @@ struct nv50_msto { struct nv50_head *head; struct nv50_mstc *mstc; bool disabled; + bool enabled; }; struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder) @@ -947,57 +948,37 @@ struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder) return msto->mstc->mstm->outp; } -static struct drm_dp_payload * -nv50_msto_payload(struct nv50_msto *msto) -{ - struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev); - struct nv50_mstc *mstc = msto->mstc; - struct nv50_mstm *mstm = mstc->mstm; - int vcpi = mstc->port->vcpi.vcpi, i; - - WARN_ON(!mutex_is_locked(&mstm->mgr.payload_lock)); - - NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi); - for (i = 0; i < mstm->mgr.max_payloads; i++) { - struct drm_dp_payload *payload = &mstm->mgr.payloads[i]; - NV_ATOMIC(drm, "%s: %d: vcpi %d start 0x%02x slots 0x%02x\n", - mstm->outp->base.base.name, i, payload->vcpi, - payload->start_slot, payload->num_slots); - } - - for (i = 0; i < mstm->mgr.max_payloads; i++) { - struct drm_dp_payload *payload = &mstm->mgr.payloads[i]; - if (payload->vcpi == vcpi) - return payload; - } - - return NULL; -} - static void -nv50_msto_cleanup(struct nv50_msto *msto) +nv50_msto_cleanup(struct drm_atomic_state *state, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_topology_mgr *mgr, + struct nv50_msto *msto) { struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev); - struct nv50_mstc *mstc = msto->mstc; - struct nv50_mstm *mstm = mstc->mstm; - - if (!msto->disabled) - return; + struct drm_dp_mst_atomic_payload *payload = + drm_atomic_get_mst_payload_state(mst_state, msto->mstc->port); NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name); - drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port); - - msto->mstc = NULL; - msto->disabled = false; + if (msto->disabled) { + msto->mstc = NULL; + msto->disabled = false; + } else if (msto->enabled) { + drm_dp_add_payload_part2(mgr, state, payload); + msto->enabled = false; + } } static void -nv50_msto_prepare(struct nv50_msto *msto) +nv50_msto_prepare(struct drm_atomic_state *state, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_topology_mgr *mgr, + struct nv50_msto *msto) { struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev); struct nv50_mstc *mstc = msto->mstc; struct nv50_mstm *mstm = mstc->mstm; + struct drm_dp_mst_atomic_payload *payload; struct { struct nv50_disp_mthd_v1 base; struct nv50_disp_sor_dp_mst_vcpi_v0 vcpi; @@ -1009,17 +990,21 @@ nv50_msto_prepare(struct nv50_msto *msto) (0x0100 << msto->head->base.index), }; - mutex_lock(&mstm->mgr.payload_lock); - NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name); - if (mstc->port->vcpi.vcpi > 0) { - struct drm_dp_payload *payload = nv50_msto_payload(msto); - if (payload) { - args.vcpi.start_slot = payload->start_slot; - args.vcpi.num_slots = payload->num_slots; - args.vcpi.pbn = mstc->port->vcpi.pbn; - args.vcpi.aligned_pbn = mstc->port->vcpi.aligned_pbn; - } + + payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port); + + // TODO: Figure out if we want to do a better job of handling VCPI allocation failures here? + if (msto->disabled) { + drm_dp_remove_payload(mgr, mst_state, payload); + } else { + if (msto->enabled) + drm_dp_add_payload_part1(mgr, mst_state, payload); + + args.vcpi.start_slot = payload->vc_start_slot; + args.vcpi.num_slots = payload->time_slots; + args.vcpi.pbn = payload->pbn; + args.vcpi.aligned_pbn = payload->time_slots * mst_state->pbn_div; } NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n", @@ -1028,7 +1013,6 @@ nv50_msto_prepare(struct nv50_msto *msto) args.vcpi.pbn, args.vcpi.aligned_pbn); nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args)); - mutex_unlock(&mstm->mgr.payload_lock); } static int @@ -1038,6 +1022,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, { struct drm_atomic_state *state = crtc_state->state; struct drm_connector *connector = conn_state->connector; + struct drm_dp_mst_topology_state *mst_state; struct nv50_mstc *mstc = nv50_mstc(connector); struct nv50_mstm *mstm = mstc->mstm; struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); @@ -1065,8 +1050,18 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, false); } - slots = drm_dp_atomic_find_time_slots(state, &mstm->mgr, mstc->port, - asyh->dp.pbn, 0); + mst_state = drm_atomic_get_mst_topology_state(state, &mstm->mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + if (!mst_state->pbn_div) { + struct nouveau_encoder *outp = mstc->mstm->outp; + + mst_state->pbn_div = drm_dp_get_vc_payload_bw(&mstm->mgr, + outp->dp.link_bw, outp->dp.link_nr); + } + + slots = drm_dp_atomic_find_time_slots(state, &mstm->mgr, mstc->port, asyh->dp.pbn); if (slots < 0) return slots; @@ -1098,7 +1093,6 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st struct drm_connector *connector; struct drm_connector_list_iter conn_iter; u8 proto; - bool r; drm_connector_list_iter_begin(encoder->dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { @@ -1113,10 +1107,6 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st if (WARN_ON(!mstc)) return; - r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, asyh->dp.pbn, asyh->dp.tu); - if (!r) - DRM_DEBUG_KMS("Failed to allocate VCPI\n"); - if (!mstm->links++) nv50_outp_acquire(mstm->outp, false /*XXX: MST audio.*/); @@ -1129,6 +1119,7 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st nv50_dp_bpc_to_depth(asyh->or.bpc)); msto->mstc = mstc; + msto->enabled = true; mstm->modified = true; } @@ -1139,8 +1130,6 @@ nv50_msto_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *s struct nv50_mstc *mstc = msto->mstc; struct nv50_mstm *mstm = mstc->mstm; - drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port); - mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0); mstm->modified = true; if (!--mstm->links) @@ -1360,7 +1349,9 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port, } static void -nv50_mstm_cleanup(struct nv50_mstm *mstm) +nv50_mstm_cleanup(struct drm_atomic_state *state, + struct drm_dp_mst_topology_state *mst_state, + struct nv50_mstm *mstm) { struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev); struct drm_encoder *encoder; @@ -1368,14 +1359,12 @@ nv50_mstm_cleanup(struct nv50_mstm *mstm) NV_ATOMIC(drm, "%s: mstm cleanup\n", mstm->outp->base.base.name); drm_dp_check_act_status(&mstm->mgr); - drm_dp_update_payload_part2(&mstm->mgr); - drm_for_each_encoder(encoder, mstm->outp->base.base.dev) { if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) { struct nv50_msto *msto = nv50_msto(encoder); struct nv50_mstc *mstc = msto->mstc; if (mstc && mstc->mstm == mstm) - nv50_msto_cleanup(msto); + nv50_msto_cleanup(state, mst_state, &mstm->mgr, msto); } } @@ -1383,20 +1372,34 @@ nv50_mstm_cleanup(struct nv50_mstm *mstm) } static void -nv50_mstm_prepare(struct nv50_mstm *mstm) +nv50_mstm_prepare(struct drm_atomic_state *state, + struct drm_dp_mst_topology_state *mst_state, + struct nv50_mstm *mstm) { struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev); struct drm_encoder *encoder; NV_ATOMIC(drm, "%s: mstm prepare\n", mstm->outp->base.base.name); - drm_dp_update_payload_part1(&mstm->mgr, 1); + /* Disable payloads first */ drm_for_each_encoder(encoder, mstm->outp->base.base.dev) { if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) { struct nv50_msto *msto = nv50_msto(encoder); struct nv50_mstc *mstc = msto->mstc; - if (mstc && mstc->mstm == mstm) - nv50_msto_prepare(msto); + if (mstc && mstc->mstm == mstm && msto->disabled) + nv50_msto_prepare(state, mst_state, &mstm->mgr, msto); + } + } + + /* Add payloads for new heads, while also updating the start slots of any unmodified (but + * active) heads that may have had their VC slots shifted left after the previous step + */ + drm_for_each_encoder(encoder, mstm->outp->base.base.dev) { + if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) { + struct nv50_msto *msto = nv50_msto(encoder); + struct nv50_mstc *mstc = msto->mstc; + if (mstc && mstc->mstm == mstm && !msto->disabled) + nv50_msto_prepare(state, mst_state, &mstm->mgr, msto); } } @@ -1593,9 +1596,7 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, mstm->mgr.cbs = &nv50_mstm; ret = drm_dp_mst_topology_mgr_init(&mstm->mgr, dev, aux, aux_max, - max_payloads, outp->dcb->dpconf.link_nr, - drm_dp_bw_code_to_link_rate(outp->dcb->dpconf.link_bw), - conn_base_id); + max_payloads, conn_base_id); if (ret) return ret; @@ -2047,20 +2048,20 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) static void nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock) { + struct drm_dp_mst_topology_mgr *mgr; + struct drm_dp_mst_topology_state *mst_state; struct nouveau_drm *drm = nouveau_drm(state->dev); struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_core *core = disp->core; struct nv50_mstm *mstm; - struct drm_encoder *encoder; + int i; NV_ATOMIC(drm, "commit core %08x\n", interlock[NV50_DISP_INTERLOCK_BASE]); - drm_for_each_encoder(encoder, drm->dev) { - if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { - mstm = nouveau_encoder(encoder)->dp.mstm; - if (mstm && mstm->modified) - nv50_mstm_prepare(mstm); - } + for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { + mstm = nv50_mstm(mgr); + if (mstm->modified) + nv50_mstm_prepare(state, mst_state, mstm); } core->func->ntfy_init(disp->sync, NV50_DISP_CORE_NTFY); @@ -2069,12 +2070,10 @@ nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock) disp->core->chan.base.device)) NV_ERROR(drm, "core notifier timeout\n"); - drm_for_each_encoder(encoder, drm->dev) { - if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { - mstm = nouveau_encoder(encoder)->dp.mstm; - if (mstm && mstm->modified) - nv50_mstm_cleanup(mstm); - } + for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { + mstm = nv50_mstm(mgr); + if (mstm->modified) + nv50_mstm_cleanup(state, mst_state, mstm); } } diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index 8b847836a0b4..43f58cef4eec 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -48,20 +48,6 @@ struct drm_dp_mst_topology_ref_history { struct drm_dp_mst_branch; -/** - * struct drm_dp_vcpi - Virtual Channel Payload Identifier - * @vcpi: Virtual channel ID. - * @pbn: Payload Bandwidth Number for this channel - * @aligned_pbn: PBN aligned with slot size - * @num_slots: number of slots for this PBN - */ -struct drm_dp_vcpi { - int vcpi; - int pbn; - int aligned_pbn; - int num_slots; -}; - /** * struct drm_dp_mst_port - MST port * @port_num: port number @@ -142,7 +128,6 @@ struct drm_dp_mst_port { struct drm_dp_aux aux; /* i2c bus for this port? */ struct drm_dp_mst_branch *parent; - struct drm_dp_vcpi vcpi; struct drm_connector *connector; struct drm_dp_mst_topology_mgr *mgr; @@ -527,19 +512,6 @@ struct drm_dp_mst_topology_cbs { void (*poll_hpd_irq)(struct drm_dp_mst_topology_mgr *mgr); }; -#define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8) - -#define DP_PAYLOAD_LOCAL 1 -#define DP_PAYLOAD_REMOTE 2 -#define DP_PAYLOAD_DELETE_LOCAL 3 - -struct drm_dp_payload { - int payload_state; - int start_slot; - int num_slots; - int vcpi; -}; - #define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base) /** @@ -552,6 +524,34 @@ struct drm_dp_mst_atomic_payload { /** @port: The MST port assigned to this payload */ struct drm_dp_mst_port *port; + /** + * @vc_start_slot: The time slot that this payload starts on. Because payload start slots + * can't be determined ahead of time, the contents of this value are UNDEFINED at atomic + * check time. This shouldn't usually matter, as the start slot should never be relevant for + * atomic state computations. + * + * Since this value is determined at commit time instead of check time, this value is + * protected by the MST helpers ensuring that async commits operating on the given topology + * never run in parallel. In the event that a driver does need to read this value (e.g. to + * inform hardware of the starting timeslot for a payload), the driver may either: + * + * * Read this field during the atomic commit after + * drm_dp_mst_atomic_wait_for_dependencies() has been called, which will ensure the + * previous MST states payload start slots have been copied over to the new state. Note + * that a new start slot won't be assigned/removed from this payload until + * drm_dp_add_payload_part1()/drm_dp_remove_payload() have been called. + * * Acquire the MST modesetting lock, and then wait for any pending MST-related commits to + * get committed to hardware by calling drm_crtc_commit_wait() on each of the + * &drm_crtc_commit structs in &drm_dp_mst_topology_state.commit_deps. + * + * If neither of the two above solutions suffice (e.g. the driver needs to read the start + * slot in the middle of an atomic commit without waiting for some reason), then drivers + * should cache this value themselves after changing payloads. + */ + s8 vc_start_slot; + + /** @vcpi: The Virtual Channel Payload Identifier */ + u8 vcpi; /** * @time_slots: * The number of timeslots allocated to this payload from the source DP Tx to @@ -579,8 +579,6 @@ struct drm_dp_mst_topology_state { /** @base: Base private state for atomic */ struct drm_private_state base; - /** @payloads: The list of payloads being created/destroyed in this state */ - struct list_head payloads; /** @mgr: The topology manager */ struct drm_dp_mst_topology_mgr *mgr; @@ -597,10 +595,21 @@ struct drm_dp_mst_topology_state { /** @num_commit_deps: The number of CRTC commits in @commit_deps */ size_t num_commit_deps; + /** @payload_mask: A bitmask of allocated VCPIs, used for VCPI assignments */ + u32 payload_mask; + /** @payloads: The list of payloads being created/destroyed in this state */ + struct list_head payloads; + /** @total_avail_slots: The total number of slots this topology can handle (63 or 64) */ u8 total_avail_slots; /** @start_slot: The first usable time slot in this topology (1 or 0) */ u8 start_slot; + + /** + * @pbn_div: The current PBN divisor for this topology. The driver is expected to fill this + * out itself. + */ + int pbn_div; }; #define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base) @@ -640,14 +649,6 @@ struct drm_dp_mst_topology_mgr { * @max_payloads: maximum number of payloads the GPU can generate. */ int max_payloads; - /** - * @max_lane_count: maximum number of lanes the GPU can drive. - */ - int max_lane_count; - /** - * @max_link_rate: maximum link rate per lane GPU can output, in kHz. - */ - int max_link_rate; /** * @conn_base_id: DRM connector ID this mgr is connected to. Only used * to build the MST connector path value. @@ -690,6 +691,20 @@ struct drm_dp_mst_topology_mgr { */ bool payload_id_table_cleared : 1; + /** + * @payload_count: The number of currently active payloads in hardware. This value is only + * intended to be used internally by MST helpers for payload tracking, and is only safe to + * read/write from the atomic commit (not check) context. + */ + u8 payload_count; + + /** + * @next_start_slot: The starting timeslot to use for new VC payloads. This value is used + * internally by MST helpers for payload tracking, and is only safe to read/write from the + * atomic commit (not check) context. + */ + u8 next_start_slot; + /** * @mst_primary: Pointer to the primary/first branch device. */ @@ -703,10 +718,6 @@ struct drm_dp_mst_topology_mgr { * @sink_count: Sink count from DEVICE_SERVICE_IRQ_VECTOR_ESI0. */ u8 sink_count; - /** - * @pbn_div: PBN to slots divisor. - */ - int pbn_div; /** * @funcs: Atomic helper callbacks @@ -723,32 +734,6 @@ struct drm_dp_mst_topology_mgr { */ struct list_head tx_msg_downq; - /** - * @payload_lock: Protect payload information. - */ - struct mutex payload_lock; - /** - * @proposed_vcpis: Array of pointers for the new VCPI allocation. The - * VCPI structure itself is &drm_dp_mst_port.vcpi, and the size of - * this array is determined by @max_payloads. - */ - struct drm_dp_vcpi **proposed_vcpis; - /** - * @payloads: Array of payloads. The size of this array is determined - * by @max_payloads. - */ - struct drm_dp_payload *payloads; - /** - * @payload_mask: Elements of @payloads actually in use. Since - * reallocation of active outputs isn't possible gaps can be created by - * disabling outputs out of order compared to how they've been enabled. - */ - unsigned long payload_mask; - /** - * @vcpi_mask: Similar to @payload_mask, but for @proposed_vcpis. - */ - unsigned long vcpi_mask; - /** * @tx_waitq: Wait to queue stall for the tx worker. */ @@ -820,9 +805,7 @@ struct drm_dp_mst_topology_mgr { int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, struct drm_device *dev, struct drm_dp_aux *aux, int max_dpcd_transaction_bytes, - int max_payloads, - int max_lane_count, int max_link_rate, - int conn_base_id); + int max_payloads, int conn_base_id); void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); @@ -845,28 +828,17 @@ int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc); -bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn, int slots); - -int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); - - -void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); - void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap); -void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port); - - -int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, - int pbn); - - -int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot); - - -int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr); +int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_atomic_payload *payload); +int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr, + struct drm_atomic_state *state, + struct drm_dp_mst_atomic_payload *payload); +void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_atomic_payload *payload); int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr); @@ -888,17 +860,22 @@ int drm_dp_mst_connector_late_register(struct drm_connector *connector, void drm_dp_mst_connector_early_unregister(struct drm_connector *connector, struct drm_dp_mst_port *port); -struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, - struct drm_dp_mst_topology_mgr *mgr); +struct drm_dp_mst_topology_state * +drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr *mgr); +struct drm_dp_mst_topology_state * +drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr *mgr); +struct drm_dp_mst_atomic_payload * +drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state, + struct drm_dp_mst_port *port); int __must_check drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn, - int pbn_div); + struct drm_dp_mst_port *port, int pbn); int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, struct drm_dp_mst_port *port, - int pbn, int pbn_div, - bool enable); + int pbn, bool enable); int __must_check drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr); @@ -922,6 +899,12 @@ void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port); struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port); +static inline struct drm_dp_mst_topology_state * +to_drm_dp_mst_topology_state(struct drm_private_state *state) +{ + return container_of(state, struct drm_dp_mst_topology_state, base); +} + extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs; /** From 227295df4e37de66b61bbb3d1f10436f0acd33cc Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Wed, 24 Aug 2022 18:13:24 +0200 Subject: [PATCH 317/396] drm/vc4: hdmi: unlock mutex when device is unplugged In vc4_hdmi_encoder_{pre,post}_crtc_enable() commit cd00ed5187bf ("drm/vc4: hdmi: Protect device resources after removal") missed to unlock the mutex before returning due to drm_dev_enter() indicating the device being unplugged. Fixes: cd00ed5187bf ("drm/vc4: hdmi: Protect device resources after removal") Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220824161327.330627-2-dakr@redhat.com --- drivers/gpu/drm/vc4/vc4_hdmi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 84e5a91c2ea7..4d3ff51ad2a8 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1425,7 +1425,7 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, mutex_lock(&vc4_hdmi->mutex); if (!drm_dev_enter(drm, &idx)) - return; + goto out; if (vc4_hdmi->variant->csc_setup) vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode); @@ -1436,6 +1436,7 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, drm_dev_exit(idx); +out: mutex_unlock(&vc4_hdmi->mutex); } @@ -1455,7 +1456,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, mutex_lock(&vc4_hdmi->mutex); if (!drm_dev_enter(drm, &idx)) - return; + goto out; spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -1516,6 +1517,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, vc4_hdmi_enable_scrambling(encoder); drm_dev_exit(idx); + +out: mutex_unlock(&vc4_hdmi->mutex); } From 6acb416bf49f818dbf0aa71aee9f6cae93a505a4 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Wed, 24 Aug 2022 18:13:25 +0200 Subject: [PATCH 318/396] drm/vc4: plane: protect device resources after removal (Hardware) resources which are bound to the driver and device lifecycle must not be accessed after the device and driver are unbound. However, the DRM device isn't freed as long as the last user closed it, hence userspace can still call into the driver. Therefore protect the critical sections which are accessing those resources with drm_dev_enter() and drm_dev_exit(). Fixes: 9872c7a31921 ("drm/vc4: plane: Switch to drmm_universal_plane_alloc()") Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220824161327.330627-3-dakr@redhat.com --- drivers/gpu/drm/vc4/vc4_plane.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index eff9c63adfa7..8b92a45a3c89 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -19,6 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_blend.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -1219,6 +1220,10 @@ u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); int i; + int idx; + + if (!drm_dev_enter(plane->dev, &idx)) + goto out; vc4_state->hw_dlist = dlist; @@ -1226,6 +1231,9 @@ u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist) for (i = 0; i < vc4_state->dlist_count; i++) writel(vc4_state->dlist[i], &dlist[i]); + drm_dev_exit(idx); + +out: return vc4_state->dlist_count; } @@ -1245,6 +1253,10 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); uint32_t addr; + int idx; + + if (!drm_dev_enter(plane->dev, &idx)) + return; /* We're skipping the address adjustment for negative origin, * because this is only called on the primary plane. @@ -1263,6 +1275,8 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) * also use our updated address. */ vc4_state->dlist[vc4_state->ptr0_offset] = addr; + + drm_dev_exit(idx); } static void vc4_plane_atomic_async_update(struct drm_plane *plane, @@ -1271,6 +1285,10 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); struct vc4_plane_state *vc4_state, *new_vc4_state; + int idx; + + if (!drm_dev_enter(plane->dev, &idx)) + return; swap(plane->state->fb, new_plane_state->fb); plane->state->crtc_x = new_plane_state->crtc_x; @@ -1333,6 +1351,8 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, &vc4_state->hw_dlist[vc4_state->pos2_offset]); writel(vc4_state->dlist[vc4_state->ptr0_offset], &vc4_state->hw_dlist[vc4_state->ptr0_offset]); + + drm_dev_exit(idx); } static int vc4_plane_atomic_async_check(struct drm_plane *plane, From e0c953034a35b85b60ccc792a7d6e5fd802d944b Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Wed, 24 Aug 2022 18:13:26 +0200 Subject: [PATCH 319/396] drm/vc4: crtc: protect device resources after removal (Hardware) resources which are bound to the driver and device lifecycle must not be accessed after the device and driver are unbound. However, the DRM device isn't freed as long as the last user closed it, hence userspace can still call into the driver. Therefore protect the critical sections which are accessing those resources with drm_dev_enter() and drm_dev_exit(). Fixes: 7cc4214c27cf ("drm/vc4: crtc: Switch to drmm_kzalloc") Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220824161327.330627-4-dakr@redhat.com --- drivers/gpu/drm/vc4/vc4_crtc.c | 41 +++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 2def6e2ad6f0..0108613e79d5 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -39,6 +39,7 @@ #include <drm/drm_atomic_uapi.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_framebuffer.h> +#include <drm/drm_drv.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> @@ -295,10 +296,17 @@ struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) { struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_device *dev = crtc->dev; + int idx; + + if (!drm_dev_enter(dev, &idx)) + return; /* The PV needs to be disabled before it can be flushed */ CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR); + + drm_dev_exit(idx); } static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encoder, @@ -321,6 +329,10 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; u8 ppc = pv_data->pixels_per_clock; bool debug_dump_regs = false; + int idx; + + if (!drm_dev_enter(dev, &idx)) + return; if (debug_dump_regs) { struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev); @@ -410,6 +422,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode drm_crtc_index(crtc)); drm_print_regset32(&p, &vc4_crtc->regset); } + + drm_dev_exit(idx); } static void require_hvs_enabled(struct drm_device *dev) @@ -430,7 +444,10 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - int ret; + int idx, ret; + + if (!drm_dev_enter(dev, &idx)) + return -ENODEV; CRTC_WRITE(PV_V_CONTROL, CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN); @@ -464,6 +481,8 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, if (vc4_encoder && vc4_encoder->post_crtc_powerdown) vc4_encoder->post_crtc_powerdown(encoder, state); + drm_dev_exit(idx); + return 0; } @@ -588,10 +607,14 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, new_state); struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); + int idx; drm_dbg(dev, "Enabling CRTC %s (%u) connected to Encoder %s (%u)", crtc->name, crtc->base.id, encoder->name, encoder->base.id); + if (!drm_dev_enter(dev, &idx)) + return; + require_hvs_enabled(dev); /* Enable vblank irq handling before crtc is started otherwise @@ -619,6 +642,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, if (vc4_encoder->post_crtc_enable) vc4_encoder->post_crtc_enable(encoder, state); + + drm_dev_exit(idx); } static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, @@ -711,17 +736,31 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc, static int vc4_enable_vblank(struct drm_crtc *crtc) { struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_device *dev = crtc->dev; + int idx; + + if (!drm_dev_enter(dev, &idx)) + return -ENODEV; CRTC_WRITE(PV_INTEN, PV_INT_VFP_START); + drm_dev_exit(idx); + return 0; } static void vc4_disable_vblank(struct drm_crtc *crtc) { struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_device *dev = crtc->dev; + int idx; + + if (!drm_dev_enter(dev, &idx)) + return; CRTC_WRITE(PV_INTEN, 0); + + drm_dev_exit(idx); } static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) From b3be4520d81e7dc820de5fdab0d7d697231cf517 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <dakr@redhat.com> Date: Wed, 24 Aug 2022 18:13:27 +0200 Subject: [PATCH 320/396] drm/vc4: hvs: protect drm_print_regset32() In vc4_hvs_dump_state() potentially freed resources are protected from being accessed with drm_dev_enter()/drm_dev_exit(). Also include drm_print_regset32() in the protected section, since drm_print_regset32() does access memory that is typically mapped via devm_* calls. Fixes: 969cfae1f01d ("drm/vc4: hvs: Protect device resources after removal") Signed-off-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://lore.kernel.org/r/20220824161327.330627-5-dakr@redhat.com --- drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 9e823e0de197..4ac9f5a2d5f9 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -71,11 +71,11 @@ void vc4_hvs_dump_state(struct vc4_hvs *hvs) struct drm_printer p = drm_info_printer(&hvs->pdev->dev); int idx, i; - drm_print_regset32(&p, &hvs->regset); - if (!drm_dev_enter(drm, &idx)) return; + drm_print_regset32(&p, &hvs->regset); + DRM_INFO("HVS ctx:\n"); for (i = 0; i < 64; i += 4) { DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n", From d9c04a1b7a15b5e74b2977461d9511e497f05d8f Mon Sep 17 00:00:00 2001 From: Vivek Kasireddy <vivek.kasireddy@intel.com> Date: Wed, 24 Aug 2022 23:35:22 -0700 Subject: [PATCH 321/396] udmabuf: Set ubuf->sg = NULL if the creation of sg table fails When userspace tries to map the dmabuf and if for some reason (e.g. OOM) the creation of the sg table fails, ubuf->sg needs to be set to NULL. Otherwise, when the userspace subsequently closes the dmabuf fd, we'd try to erroneously free the invalid sg table from release_udmabuf resulting in the following crash reported by syzbot: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 0 PID: 3609 Comm: syz-executor487 Not tainted 5.19.0-syzkaller-13930-g7ebfc85e2cd7 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/22/2022 RIP: 0010:dma_unmap_sgtable include/linux/dma-mapping.h:378 [inline] RIP: 0010:put_sg_table drivers/dma-buf/udmabuf.c:89 [inline] RIP: 0010:release_udmabuf+0xcb/0x4f0 drivers/dma-buf/udmabuf.c:114 Code: 48 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 2b 04 00 00 48 8d 7d 0c 4c 8b 63 30 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 e2 RSP: 0018:ffffc900037efd30 EFLAGS: 00010246 RAX: dffffc0000000000 RBX: ffffffff8cb67800 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff84ad27e0 RDI: 0000000000000000 RBP: fffffffffffffff4 R08: 0000000000000005 R09: 0000000000000000 R10: 0000000000000000 R11: 000000000008c07c R12: ffff88801fa05000 R13: ffff888073db07e8 R14: ffff888025c25440 R15: 0000000000000000 FS: 0000555555fc4300(0000) GS:ffff8880b9a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fc1c0ce06e4 CR3: 00000000715e6000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> dma_buf_release+0x157/0x2d0 drivers/dma-buf/dma-buf.c:78 __dentry_kill+0x42b/0x640 fs/dcache.c:612 dentry_kill fs/dcache.c:733 [inline] dput+0x806/0xdb0 fs/dcache.c:913 __fput+0x39c/0x9d0 fs/file_table.c:333 task_work_run+0xdd/0x1a0 kernel/task_work.c:177 ptrace_notify+0x114/0x140 kernel/signal.c:2353 ptrace_report_syscall include/linux/ptrace.h:420 [inline] ptrace_report_syscall_exit include/linux/ptrace.h:482 [inline] syscall_exit_work kernel/entry/common.c:249 [inline] syscall_exit_to_user_mode_prepare+0x129/0x280 kernel/entry/common.c:276 __syscall_exit_to_user_mode_work kernel/entry/common.c:281 [inline] syscall_exit_to_user_mode+0x9/0x50 kernel/entry/common.c:294 do_syscall_64+0x42/0xb0 arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7fc1c0c35b6b Code: 0f 05 48 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 0c e8 63 fc ff ff 8b 7c 24 0c 41 89 c0 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 35 44 89 c7 89 44 24 0c e8 a1 fc ff ff 8b 44 RSP: 002b:00007ffd78a06090 EFLAGS: 00000293 ORIG_RAX: 0000000000000003 RAX: 0000000000000000 RBX: 0000000000000007 RCX: 00007fc1c0c35b6b RDX: 0000000020000280 RSI: 0000000040086200 RDI: 0000000000000006 RBP: 0000000000000007 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000293 R12: 000000000000000c R13: 0000000000000003 R14: 00007fc1c0cfe4a0 R15: 00007ffd78a06140 </TASK> Modules linked in: ---[ end trace 0000000000000000 ]--- RIP: 0010:dma_unmap_sgtable include/linux/dma-mapping.h:378 [inline] RIP: 0010:put_sg_table drivers/dma-buf/udmabuf.c:89 [inline] RIP: 0010:release_udmabuf+0xcb/0x4f0 drivers/dma-buf/udmabuf.c:114 Reported-by: syzbot+c80e9ef5d8bb45894db0@syzkaller.appspotmail.com Cc: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220825063522.801264-1-vivek.kasireddy@intel.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/dma-buf/udmabuf.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 38e8767ec371..bf11d32205f3 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -124,17 +124,20 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, { struct udmabuf *ubuf = buf->priv; struct device *dev = ubuf->device->this_device; + int ret = 0; if (!ubuf->sg) { ubuf->sg = get_sg_table(dev, buf, direction); - if (IS_ERR(ubuf->sg)) - return PTR_ERR(ubuf->sg); + if (IS_ERR(ubuf->sg)) { + ret = PTR_ERR(ubuf->sg); + ubuf->sg = NULL; + } } else { dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, direction); } - return 0; + return ret; } static int end_cpu_udmabuf(struct dma_buf *buf, From 3007dc2af6e86ac00b4daf7414142637fdf50bfa Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Fri, 12 Aug 2022 15:40:00 -0700 Subject: [PATCH 322/396] drm/virtio: Fix same-context optimization When VIRTGPU_EXECBUF_RING_IDX is used, we should be considering the timeline that the EB if running on rather than the global driver fence context. Fixes: 85c83ea915ed ("drm/virtio: implement context init: allocate an array of fence contexts") Signed-off-by: Rob Clark <robdclark@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20220812224001.2806463-1-robdclark@gmail.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 9b2702116f93..3b1701607aae 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -168,7 +168,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, * array contains any fence from a foreign context. */ ret = 0; - if (!dma_fence_match_context(in_fence, vgdev->fence_drv.context)) + if (!dma_fence_match_context(in_fence, fence_ctx + ring_idx)) ret = dma_fence_wait(in_fence, true); dma_fence_put(in_fence); From 84dfc46594b0167e5d3736273b0e0e05365da641 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Mon, 22 Aug 2022 17:42:27 -0700 Subject: [PATCH 323/396] drm/panel: use 'select' for Ili9341 panel driver helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use 'select' instead of 'depends on' for DRM helpers for the Ilitek ILI9341 panel driver. This is what is done in the vast majority of other cases and this makes it possible to fix a build error with drm_mipi_dbi. Fixes: 5a04227326b0 ("drm/panel: Add ilitek ili9341 panel driver") Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Cc: Dillon Min <dillon.minfei@gmail.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Noralf Trønnes <noralf@tronnes.org> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: dri-devel@lists.freedesktop.org Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220823004227.10820-1-rdunlap@infradead.org --- drivers/gpu/drm/panel/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 584a69f99af6..a582ddd583c2 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -165,8 +165,8 @@ config DRM_PANEL_ILITEK_IL9322 config DRM_PANEL_ILITEK_ILI9341 tristate "Ilitek ILI9341 240x320 QVGA panels" depends on OF && SPI - depends on DRM_KMS_HELPER - depends on DRM_GEM_DMA_HELPER + select DRM_KMS_HELPER + select DRM_GEM_DMA_HELPER depends on BACKLIGHT_CLASS_DEVICE select DRM_MIPI_DBI help From eb7de496451bd969e203f02f66585131228ba4ae Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Mon, 22 Aug 2022 17:42:43 -0700 Subject: [PATCH 324/396] drm: fix drm_mipi_dbi build errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_mipi_dbi needs lots of DRM_KMS_HELPER support, so select that Kconfig symbol like it is done is most other uses, and the way that it was before MIPS_DBI was moved from tinydrm to its core location. Fixes these build errors: ld: drivers/gpu/drm/drm_mipi_dbi.o: in function `mipi_dbi_buf_copy': drivers/gpu/drm/drm_mipi_dbi.c:205: undefined reference to `drm_gem_fb_get_obj' ld: drivers/gpu/drm/drm_mipi_dbi.c:211: undefined reference to `drm_gem_fb_begin_cpu_access' ld: drivers/gpu/drm/drm_mipi_dbi.c:215: undefined reference to `drm_gem_fb_vmap' ld: drivers/gpu/drm/drm_mipi_dbi.c:222: undefined reference to `drm_fb_swab' ld: drivers/gpu/drm/drm_mipi_dbi.c:224: undefined reference to `drm_fb_memcpy' ld: drivers/gpu/drm/drm_mipi_dbi.c:227: undefined reference to `drm_fb_xrgb8888_to_rgb565' ld: drivers/gpu/drm/drm_mipi_dbi.c:235: undefined reference to `drm_gem_fb_vunmap' ld: drivers/gpu/drm/drm_mipi_dbi.c:237: undefined reference to `drm_gem_fb_end_cpu_access' ld: drivers/gpu/drm/drm_mipi_dbi.o: in function `mipi_dbi_dev_init_with_formats': ld: drivers/gpu/drm/drm_mipi_dbi.o:/X64/../drivers/gpu/drm/drm_mipi_dbi.c:469: undefined reference to `drm_gem_fb_create_with_dirty' Fixes: 174102f4de23 ("drm/tinydrm: Move mipi-dbi") Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Reported-by: kernel test robot <lkp@intel.com> Cc: Dillon Min <dillon.minfei@gmail.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Noralf Trønnes <noralf@tronnes.org> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: dri-devel@lists.freedesktop.org Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220823004243.11596-1-rdunlap@infradead.org --- drivers/gpu/drm/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 0b2ad7212ee6..2f52e8941074 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -31,6 +31,7 @@ menuconfig DRM config DRM_MIPI_DBI tristate depends on DRM + select DRM_KMS_HELPER config DRM_MIPI_DSI bool From 4d054ca9ad01004901f3ba988d77f7d298819c12 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Mon, 1 Aug 2022 15:15:55 +0200 Subject: [PATCH 325/396] drm: bridge: icn6211: Add and use hs_rate and lp_rate Fill in hs_rate and lp_rate to struct mipi_dsi_device for this bridge and adjust DSI input frequency calculations such that they expect the DSI host to configure HS clock according to hs_rate. This is an optimization for the DSI burst mode case. In case the DSI device supports DSI burst mode, it is recommended to operate the DSI interface at the highest possible HS clock frequency which the DSI device supports. This permits the DSI host to send as short as possible bursts of data on the DSI link and keep the DSI data lanes in LP mode otherwise, which reduces power consumption. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Robert Foss <robert.foss@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: dri-devel@lists.freedesktop.org Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220801131555.182969-1-marex@denx.de --- drivers/gpu/drm/bridge/chipone-icn6211.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index b07d2d16c3cf..5db0224d783f 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -259,7 +259,7 @@ static void chipone_configure_pll(struct chipone *icn, /* * DSI byte clock frequency (input into PLL) is calculated as: - * DSI_CLK = mode clock * bpp / dsi_data_lanes / 8 + * DSI_CLK = HS clock / 4 * * DPI pixel clock frequency (output from PLL) is mode clock. * @@ -273,8 +273,7 @@ static void chipone_configure_pll(struct chipone *icn, * It seems the PLL input clock after applying P pre-divider have * to be lower than 20 MHz. */ - fin = mode_clock * mipi_dsi_pixel_format_to_bpp(icn->dsi->format) / - icn->dsi->lanes / 8; /* in Hz */ + fin = icn->dsi->hs_rate / 4; /* in Hz */ /* Minimum value of P predivider for PLL input in 5..20 MHz */ p_min = clamp(DIV_ROUND_UP(fin, 20000000), 1U, 31U); @@ -515,6 +514,8 @@ static int chipone_dsi_attach(struct chipone *icn) dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; + dsi->hs_rate = 500000000; + dsi->lp_rate = 16000000; ret = mipi_dsi_attach(dsi); if (ret < 0) From a2d6447a4a8ab314a6f82ab99f218689f9b0c306 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Mon, 1 Aug 2022 15:17:46 +0200 Subject: [PATCH 326/396] dt-bindings: display: bridge: icn6211: Add support for external REFCLK The ICN6211 is capable of deriving its internal PLL clock from either MIPI DSI HS clock, external REFCLK clock, or even internal oscillator. Currently supported is only the first option. Document support for external REFCLK clock input in addition to that. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Rob Herring <robh@kernel.org> Cc: Robert Foss <robert.foss@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: dri-devel@lists.freedesktop.org Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220801131747.183041-1-marex@denx.de --- .../bindings/display/bridge/chipone,icn6211.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml b/Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml index 4f0b7c71313c..5fb54375aeb6 100644 --- a/Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml +++ b/Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml @@ -24,6 +24,15 @@ properties: maxItems: 1 description: virtual channel number of a DSI peripheral + clock-names: + const: refclk + + clocks: + maxItems: 1 + description: | + Optional external clock connected to REF_CLK input. + The clock rate must be in 10..154 MHz range. + enable-gpios: description: Bridge EN pin, chip is reset when EN is low. From 378e0f9f0b3e03a84db5ed5d3da3850871e9209e Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Mon, 1 Aug 2022 15:17:47 +0200 Subject: [PATCH 327/396] drm: bridge: icn6211: Add support for external REFCLK The ICN6211 is capable of deriving its internal PLL clock from either MIPI DSI HS clock, external REFCLK clock, or even internal oscillator. Currently supported is only the first option. Add support for external REFCLK clock input in addition to that. There is little difference between these options, except that in case of MIPI DSI HS clock input, the HS clock are pre-divided by a fixed /4 divider before being fed to the PLL input, while in case of external REFCLK, the RECLK clock are fed directly into the PLL input. Per exceptionally poor documentation, the REFCLK must be in range of 10..154 MHz. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Robert Foss <robert.foss@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: dri-devel@lists.freedesktop.org Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220801131747.183041-2-marex@denx.de --- drivers/gpu/drm/bridge/chipone-icn6211.c | 39 +++++++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 5db0224d783f..bf920c3503aa 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -11,6 +11,7 @@ #include <linux/bitfield.h> #include <linux/bits.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> @@ -151,6 +152,8 @@ struct chipone { struct regulator *vdd1; struct regulator *vdd2; struct regulator *vdd3; + struct clk *refclk; + unsigned long refclk_rate; bool interface_i2c; }; @@ -273,7 +276,10 @@ static void chipone_configure_pll(struct chipone *icn, * It seems the PLL input clock after applying P pre-divider have * to be lower than 20 MHz. */ - fin = icn->dsi->hs_rate / 4; /* in Hz */ + if (icn->refclk) + fin = icn->refclk_rate; + else + fin = icn->dsi->hs_rate / 4; /* in Hz */ /* Minimum value of P predivider for PLL input in 5..20 MHz */ p_min = clamp(DIV_ROUND_UP(fin, 20000000), 1U, 31U); @@ -318,16 +324,18 @@ static void chipone_configure_pll(struct chipone *icn, best_p_pot = !(best_p & 1); dev_dbg(icn->dev, - "PLL: P[3:0]=%d P[4]=2*%d M=%d S[7:5]=2^%d delta=%d => DSI f_in=%d Hz ; DPI f_out=%d Hz\n", + "PLL: P[3:0]=%d P[4]=2*%d M=%d S[7:5]=2^%d delta=%d => DSI f_in(%s)=%d Hz ; DPI f_out=%d Hz\n", best_p >> best_p_pot, best_p_pot, best_m, best_s + 1, - min_delta, fin, (fin * best_m) / (best_p << (best_s + 1))); + min_delta, icn->refclk ? "EXT" : "DSI", fin, + (fin * best_m) / (best_p << (best_s + 1))); ref_div = PLL_REF_DIV_P(best_p >> best_p_pot) | PLL_REF_DIV_S(best_s); if (best_p_pot) /* Prefer /2 pre-divider */ ref_div |= PLL_REF_DIV_Pe; - /* Clock source selection fixed to MIPI DSI clock lane */ - chipone_writeb(icn, PLL_CTRL(6), PLL_CTRL_6_MIPI_CLK); + /* Clock source selection either external clock or MIPI DSI clock lane */ + chipone_writeb(icn, PLL_CTRL(6), + icn->refclk ? PLL_CTRL_6_EXTERNAL : PLL_CTRL_6_MIPI_CLK); chipone_writeb(icn, PLL_REF_DIV, ref_div); chipone_writeb(icn, PLL_INT(0), best_m); } @@ -463,6 +471,11 @@ static void chipone_atomic_pre_enable(struct drm_bridge *bridge, "failed to enable VDD3 regulator: %d\n", ret); } + ret = clk_prepare_enable(icn->refclk); + if (ret) + DRM_DEV_ERROR(icn->dev, + "failed to enable RECLK clock: %d\n", ret); + gpiod_set_value(icn->enable_gpio, 1); usleep_range(10000, 11000); @@ -473,6 +486,8 @@ static void chipone_atomic_post_disable(struct drm_bridge *bridge, { struct chipone *icn = bridge_to_chipone(bridge); + clk_disable_unprepare(icn->refclk); + if (icn->vdd1) regulator_disable(icn->vdd1); @@ -618,6 +633,20 @@ static int chipone_parse_dt(struct chipone *icn) struct device *dev = icn->dev; int ret; + icn->refclk = devm_clk_get_optional(dev, "refclk"); + if (IS_ERR(icn->refclk)) { + ret = PTR_ERR(icn->refclk); + DRM_DEV_ERROR(dev, "failed to get REFCLK clock: %d\n", ret); + return ret; + } else if (icn->refclk) { + icn->refclk_rate = clk_get_rate(icn->refclk); + if (icn->refclk_rate < 10000000 || icn->refclk_rate > 154000000) { + DRM_DEV_ERROR(dev, "REFCLK out of range: %ld Hz\n", + icn->refclk_rate); + return -EINVAL; + } + } + icn->vdd1 = devm_regulator_get_optional(dev, "vdd1"); if (IS_ERR(icn->vdd1)) { ret = PTR_ERR(icn->vdd1); From 61a9fa154d217c13eea90aa5bc635bc4b1fcb66e Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 5 May 2022 23:50:19 +0200 Subject: [PATCH 328/396] drm/tve200: Fix smatch warning The "ret" variable is ambiguously returning something that could be zero in the tve200_modeset_init() function, assign it an explicit error return code to make this unambiguous. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220505215019.2332613-1-linus.walleij@linaro.org --- drivers/gpu/drm/tve200/tve200_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index 79d790ae1670..04db72e3fa9c 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -64,7 +64,7 @@ static int tve200_modeset_init(struct drm_device *dev) struct tve200_drm_dev_private *priv = dev->dev_private; struct drm_panel *panel; struct drm_bridge *bridge; - int ret = 0; + int ret; drm_mode_config_init(dev); mode_config = &dev->mode_config; @@ -92,6 +92,7 @@ static int tve200_modeset_init(struct drm_device *dev) * method to get the connector out of the bridge. */ dev_err(dev->dev, "the bridge is not a panel\n"); + ret = -EINVAL; goto out_bridge; } From a7c7d23649f1fc3a73507d2aab3a5010a7b6745d Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Date: Fri, 10 Jun 2022 15:09:25 +0200 Subject: [PATCH 329/396] drm/gma500: Fix SDVO command debug printing At some point the DRM printers started adding a newline after each print. This caused SDVO command debug printing to look weird. Fix this by using snprintf to print into a buffer which can be printed as a whole by DRM_DEBUG_KMS(). Code is heavily inspired by i915. Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Acked-by: Daniel Vetter <daniel@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220610130925.8650-1-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 62 ++++++++++++++++--------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index a85aace25548..bdced46dd333 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -400,26 +400,38 @@ static const struct _sdvo_cmd_name { #define IS_SDVOB(reg) (reg == SDVOB) #define SDVO_NAME(svdo) (IS_SDVOB((svdo)->sdvo_reg) ? "SDVOB" : "SDVOC") -static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, - const void *args, int args_len) +static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo, + u8 cmd, const void *args, int args_len) { - int i; + struct drm_device *dev = psb_intel_sdvo->base.base.dev; + int i, pos = 0; + char buffer[73]; + +#define BUF_PRINT(args...) \ + pos += snprintf(buffer + pos, max_t(int, sizeof(buffer) - pos, 0), args) + + for (i = 0; i < args_len; i++) { + BUF_PRINT("%02X ", ((u8 *)args)[i]); + } + + for (; i < 8; i++) { + BUF_PRINT(" "); + } - DRM_DEBUG_KMS("%s: W: %02X ", - SDVO_NAME(psb_intel_sdvo), cmd); - for (i = 0; i < args_len; i++) - DRM_DEBUG_KMS("%02X ", ((u8 *)args)[i]); - for (; i < 8; i++) - DRM_DEBUG_KMS(" "); for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) { if (cmd == sdvo_cmd_names[i].cmd) { - DRM_DEBUG_KMS("(%s)", sdvo_cmd_names[i].name); + BUF_PRINT("(%s)", sdvo_cmd_names[i].name); break; } } + if (i == ARRAY_SIZE(sdvo_cmd_names)) - DRM_DEBUG_KMS("(%02X)", cmd); - DRM_DEBUG_KMS("\n"); + BUF_PRINT("(%02X)", cmd); + + drm_WARN_ON(dev, pos >= sizeof(buffer) - 1); +#undef BUF_PRINT + + DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(psb_intel_sdvo), cmd, buffer); } static const char *cmd_status_names[] = { @@ -490,13 +502,13 @@ static bool psb_intel_sdvo_write_cmd(struct psb_intel_sdvo *psb_intel_sdvo, u8 c } static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo, - void *response, int response_len) + void *response, int response_len) { + struct drm_device *dev = psb_intel_sdvo->base.base.dev; + char buffer[73]; + int i, pos = 0; u8 retry = 5; u8 status; - int i; - - DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(psb_intel_sdvo)); /* * The documentation states that all commands will be @@ -520,10 +532,13 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo, goto log_fail; } +#define BUF_PRINT(args...) \ + pos += snprintf(buffer + pos, max_t(int, sizeof(buffer) - pos, 0), args) + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - DRM_DEBUG_KMS("(%s)", cmd_status_names[status]); + BUF_PRINT("(%s)", cmd_status_names[status]); else - DRM_DEBUG_KMS("(??? %d)", status); + BUF_PRINT("(??? %d)", status); if (status != SDVO_CMD_STATUS_SUCCESS) goto log_fail; @@ -534,13 +549,18 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo, SDVO_I2C_RETURN_0 + i, &((u8 *)response)[i])) goto log_fail; - DRM_DEBUG_KMS(" %02X", ((u8 *)response)[i]); + BUF_PRINT(" %02X", ((u8 *)response)[i]); } - DRM_DEBUG_KMS("\n"); + + drm_WARN_ON(dev, pos >= sizeof(buffer) - 1); +#undef BUF_PRINT + + DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(psb_intel_sdvo), buffer); return true; log_fail: - DRM_DEBUG_KMS("... failed\n"); + DRM_DEBUG_KMS("%s: R: ... failed %s\n", + SDVO_NAME(psb_intel_sdvo), buffer); return false; } From 291f269a49916a8494526edca92afed69270241f Mon Sep 17 00:00:00 2001 From: Jason Wang <wangborong@cdjrlc.com> Date: Thu, 4 Aug 2022 19:47:51 +0800 Subject: [PATCH 330/396] drm/gma500: Fix comment typo The double `the' is duplicated in the comment, remove one. Signed-off-by: Jason Wang <wangborong@cdjrlc.com> Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220804114751.46714-1-wangborong@cdjrlc.com --- drivers/gpu/drm/gma500/cdv_intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index bb2e9d64018a..53b967282d6a 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -115,7 +115,7 @@ i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) /* * Write a single byte to the current I2C address, the - * the I2C link must be running or this returns -EIO + * I2C link must be running or this returns -EIO */ static int i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) From f8e1fa0fc8bd13122324da7d1e80d66641220680 Mon Sep 17 00:00:00 2001 From: Xin Ji <xji@analogixsemi.com> Date: Tue, 26 Jul 2022 11:30:58 +0800 Subject: [PATCH 331/396] drm/bridge: anx7625: Support HDMI_I2S audio format 1. Support HDMI_I2S audio format. 2. Return 0 if there is no sink connection in .hw_param callback. Signed-off-by: Xin Ji <xji@analogixsemi.com> Acked-by: Hsin-Yi Wang <hsinyi@chromium.org> Acked-by: Jiaxin Yu<jiaxin.yu@mediatek.com> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220726033058.403715-1-xji@analogixsemi.com --- drivers/gpu/drm/bridge/analogix/anx7625.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 79fc7a50b497..c74b5df4cade 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1797,8 +1797,13 @@ static int anx7625_audio_hw_params(struct device *dev, void *data, int wl, ch, rate; int ret = 0; - if (fmt->fmt != HDMI_DSP_A) { - DRM_DEV_ERROR(dev, "only supports DSP_A\n"); + if (anx7625_sink_detect(ctx) == connector_status_disconnected) { + DRM_DEV_DEBUG_DRIVER(dev, "DP not connected\n"); + return 0; + } + + if (fmt->fmt != HDMI_DSP_A && fmt->fmt != HDMI_I2S) { + DRM_DEV_ERROR(dev, "only supports DSP_A & I2S\n"); return -EINVAL; } @@ -1806,10 +1811,16 @@ static int anx7625_audio_hw_params(struct device *dev, void *data, params->sample_rate, params->sample_width, params->cea.channels); - ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client, - AUDIO_CHANNEL_STATUS_6, - ~I2S_SLAVE_MODE, - TDM_SLAVE_MODE); + if (fmt->fmt == HDMI_DSP_A) + ret = anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client, + AUDIO_CHANNEL_STATUS_6, + ~I2S_SLAVE_MODE, + TDM_SLAVE_MODE); + else + ret = anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client, + AUDIO_CHANNEL_STATUS_6, + ~TDM_SLAVE_MODE, + I2S_SLAVE_MODE); /* Word length */ switch (params->sample_width) { From d688f6b5525d5bc1b88c198959274d53a1a24204 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Mon, 25 Jul 2022 00:43:17 +0200 Subject: [PATCH 332/396] drm/bridge: tc358767: Handle bridge past DPI output Currently the driver only handles panel directly connected to the DPI output. Handle the case where a bridge is connected past DPI output of this bridge. This could be e.g. DPI to LVDS encoder chip. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Maxime Ripard <maxime@cerno.tech> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Robert Foss <robert.foss@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220724224317.288727-1-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index baaed4d37911..89e060b273ef 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1913,22 +1913,23 @@ static int tc_mipi_dsi_host_attach(struct tc_data *tc) static int tc_probe_dpi_bridge_endpoint(struct tc_data *tc) { struct device *dev = tc->dev; + struct drm_bridge *bridge; struct drm_panel *panel; int ret; /* port@1 is the DPI input/output port */ - ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, &bridge); if (ret && ret != -ENODEV) return ret; if (panel) { - struct drm_bridge *panel_bridge; + bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); + } - panel_bridge = devm_drm_panel_bridge_add(dev, panel); - if (IS_ERR(panel_bridge)) - return PTR_ERR(panel_bridge); - - tc->panel_bridge = panel_bridge; + if (bridge) { + tc->panel_bridge = bridge; tc->bridge.type = DRM_MODE_CONNECTOR_DPI; tc->bridge.funcs = &tc_dpi_bridge_funcs; From 81dae1f34d56b5a25659d03ffe63be69aca87352 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Mon, 1 Aug 2022 14:54:19 +0200 Subject: [PATCH 333/396] drm/bridge: lvds-codec: Fix error checking of drm_of_lvds_get_data_mapping() The drm_of_lvds_get_data_mapping() returns either negative value on error or MEDIA_BUS_FMT_* otherwise. The check for 'ret' would also catch the positive case of MEDIA_BUS_FMT_* and lead to probe failure every time 'data-mapping' DT property is specified. Fixes: 7c4dd0a266527 ("drm: of: Add drm_of_lvds_get_data_mapping") Signed-off-by: Marek Vasut <marex@denx.de> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Sam Ravnborg <sam@ravnborg.org> To: dri-devel@lists.freedesktop.org Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220801125419.167562-1-marex@denx.de --- drivers/gpu/drm/bridge/lvds-codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index 702ea803a743..39e7004de720 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -180,7 +180,7 @@ static int lvds_codec_probe(struct platform_device *pdev) of_node_put(bus_node); if (ret == -ENODEV) { dev_warn(dev, "missing 'data-mapping' DT property\n"); - } else if (ret) { + } else if (ret < 0) { dev_err(dev, "invalid 'data-mapping' DT property\n"); return ret; } else { From da09daf881082266e4075657fac53c7966de8e4d Mon Sep 17 00:00:00 2001 From: Lucas Stach <l.stach@pengutronix.de> Date: Fri, 26 Aug 2022 20:57:33 +0200 Subject: [PATCH 334/396] drm: bridge: dw_hdmi: only trigger hotplug event on link change There are two events that signal a real change of the link state: HPD going high means the sink is newly connected or wants the source to re-read the EDID, RX sense going low is a indication that the link has been disconnected. Ignore the other two events that also trigger interrupts, but don't need immediate attention: HPD going low does not necessarily mean the link has been lost and should not trigger a immediate read of the status. RX sense going high also does not require a detect cycle, as HPD going high is the right point in time to read the EDID. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> (v1) Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220826185733.3213248-1-l.stach@pengutronix.de --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 25a60eb4d67c..40d8ca37f5bc 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -3096,6 +3096,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) { struct dw_hdmi *hdmi = dev_id; u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat; + enum drm_connector_status status = connector_status_unknown; intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); @@ -3134,13 +3135,15 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); mutex_unlock(&hdmi->cec_notifier_mutex); } + + if (phy_stat & HDMI_PHY_HPD) + status = connector_status_connected; + + if (!(phy_stat & (HDMI_PHY_HPD | HDMI_PHY_RX_SENSE))) + status = connector_status_disconnected; } - if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { - enum drm_connector_status status = phy_int_pol & HDMI_PHY_HPD - ? connector_status_connected - : connector_status_disconnected; - + if (status != connector_status_unknown) { dev_dbg(hdmi->dev, "EVENT=%s\n", status == connector_status_connected ? "plugin" : "plugout"); From 55453c0914d9b81e75c5c83adb2dd9382da2c79d Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang <hsinyi@chromium.org> Date: Mon, 15 Aug 2022 17:39:07 +0800 Subject: [PATCH 335/396] drm/bridge: ps8640: Add double reset T4 and T5 to power-on sequence The double reset power-on sequence is a workaround for the hardware flaw in some chip that SPI Clock output glitch and cause internal MPU unable to read firmware correctly. The sequence is suggested in ps8640 application note. Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org> Reviewed-by: Rock Chiu <rock.chiu@paradetech.corp-partner.google.com> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220815093905.134164-1-hsinyi@chromium.org --- drivers/gpu/drm/bridge/parade-ps8640.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 49107a6cdac1..d7483c13c569 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -375,6 +375,11 @@ static int __maybe_unused ps8640_resume(struct device *dev) gpiod_set_value(ps_bridge->gpio_reset, 1); usleep_range(2000, 2500); gpiod_set_value(ps_bridge->gpio_reset, 0); + /* Double reset for T4 and T5 */ + msleep(50); + gpiod_set_value(ps_bridge->gpio_reset, 1); + msleep(50); + gpiod_set_value(ps_bridge->gpio_reset, 0); /* * Mystery 200 ms delay for the "MCU to be ready". It's unclear if From 5b04aab6d49578eacd6d341e281c70a769f96126 Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Mon, 15 Aug 2022 11:58:34 +0300 Subject: [PATCH 336/396] drm/dp: add drm_dp_phy_name() for getting DP PHY name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper for getting the DP PHY name. In the interest of caller simplicity and to avoid allocations and passing in of buffers, duplicate the const strings to return. It's a minor penalty to pay for simplicity in all the call sites. v2: Rebase, add kernel-doc, ensure non-NULL always Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/b08dc12a7e621a48ec35546d6cd1ed4b1434810d.1660553850.git.jani.nikula@intel.com --- drivers/gpu/drm/display/drm_dp_helper.c | 32 +++++++++++++++++++++++++ include/drm/display/drm_dp_helper.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index 32b295003f49..92990a3d577a 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -390,6 +390,38 @@ void drm_dp_link_train_channel_eq_delay(const struct drm_dp_aux *aux, } EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay); +/** + * drm_dp_phy_name() - Get the name of the given DP PHY + * @dp_phy: The DP PHY identifier + * + * Given the @dp_phy, get a user friendly name of the DP PHY, either "DPRX" or + * "LTTPR <N>", or "<INVALID DP PHY>" on errors. The returned string is always + * non-NULL and valid. + * + * Returns: Name of the DP PHY. + */ +const char *drm_dp_phy_name(enum drm_dp_phy dp_phy) +{ + static const char * const phy_names[] = { + [DP_PHY_DPRX] = "DPRX", + [DP_PHY_LTTPR1] = "LTTPR 1", + [DP_PHY_LTTPR2] = "LTTPR 2", + [DP_PHY_LTTPR3] = "LTTPR 3", + [DP_PHY_LTTPR4] = "LTTPR 4", + [DP_PHY_LTTPR5] = "LTTPR 5", + [DP_PHY_LTTPR6] = "LTTPR 6", + [DP_PHY_LTTPR7] = "LTTPR 7", + [DP_PHY_LTTPR8] = "LTTPR 8", + }; + + if (dp_phy < 0 || dp_phy >= ARRAY_SIZE(phy_names) || + WARN_ON(!phy_names[dp_phy])) + return "<INVALID DP PHY>"; + + return phy_names[dp_phy]; +} +EXPORT_SYMBOL(drm_dp_phy_name); + void drm_dp_lttpr_link_train_clock_recovery_delay(void) { usleep_range(100, 200); diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index db0fe9f8a612..ab55453f2d2c 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -69,6 +69,8 @@ bool drm_dp_128b132b_link_training_failed(const u8 link_status[DP_LINK_STATUS_SI u8 drm_dp_link_rate_to_bw_code(int link_rate); int drm_dp_bw_code_to_link_rate(u8 link_bw); +const char *drm_dp_phy_name(enum drm_dp_phy dp_phy); + /** * struct drm_dp_vsc_sdp - drm DP VSC SDP * From 1ff673333d46d2c1b053ebd0c1c7c7c79e36943e Mon Sep 17 00:00:00 2001 From: Zheyu Ma <zheyuma97@gmail.com> Date: Tue, 30 Aug 2022 15:34:50 +0800 Subject: [PATCH 337/396] drm/bridge: megachips: Fix a null pointer dereference bug When removing the module we will get the following warning: [ 31.911505] i2c-core: driver [stdp2690-ge-b850v3-fw] unregistered [ 31.912484] general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN PTI [ 31.913338] KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] [ 31.915280] RIP: 0010:drm_bridge_remove+0x97/0x130 [ 31.921825] Call Trace: [ 31.922533] stdp4028_ge_b850v3_fw_remove+0x34/0x60 [megachips_stdpxxxx_ge_b850v3_fw] [ 31.923139] i2c_device_remove+0x181/0x1f0 The two bridges (stdp2690, stdp4028) do not probe at the same time, so the driver does not call ge_b850v3_resgiter() when probing, causing the driver to try to remove the object that has not been initialized. Fix this by checking whether both the bridges are probed. Fixes: 11632d4aa2b3 ("drm/bridge: megachips: Ensure both bridges are probed before registration") Signed-off-by: Zheyu Ma <zheyuma97@gmail.com> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220830073450.1897020-1-zheyuma97@gmail.com --- drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index cce98bf2a4e7..72248a565579 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -296,7 +296,9 @@ static void ge_b850v3_lvds_remove(void) * This check is to avoid both the drivers * removing the bridge in their remove() function */ - if (!ge_b850v3_lvds_ptr) + if (!ge_b850v3_lvds_ptr || + !ge_b850v3_lvds_ptr->stdp2690_i2c || + !ge_b850v3_lvds_ptr->stdp4028_i2c) goto out; drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge); From 7c1dceaffd99247bf443606730515b54d6285969 Mon Sep 17 00:00:00 2001 From: Pin-yen Lin <treapking@chromium.org> Date: Tue, 30 Aug 2022 12:57:56 +0800 Subject: [PATCH 338/396] drm/bridge: it6505: Fix the order of DP_SET_POWER commands Send DP_SET_POWER_D3 command to the downstream before stopping DP, so the suspend process will not be interrupted by the HPD interrupt. Also modify the order in .atomic_enable callback to make the callbacks symmetric. Fixes: 46ca7da7f1e8 ("drm/bridge: it6505: Send DPCD SET_POWER to downstream") Signed-off-by: Pin-yen Lin <treapking@chromium.org> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220830045756.1655954-1-treapking@chromium.org --- drivers/gpu/drm/bridge/ite-it6505.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index f9251ec49bf0..2bb957cffd94 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -2951,9 +2951,6 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, if (ret) dev_err(dev, "Failed to setup AVI infoframe: %d", ret); - it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, - DP_SET_POWER_D0); - it6505_update_video_parameter(it6505, mode); ret = it6505_send_video_infoframe(it6505, &frame); @@ -2963,6 +2960,9 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, it6505_int_mask_enable(it6505); it6505_video_reset(it6505); + + it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, + DP_SET_POWER_D0); } static void it6505_bridge_atomic_disable(struct drm_bridge *bridge, @@ -2974,9 +2974,9 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge, DRM_DEV_DEBUG_DRIVER(dev, "start"); if (it6505->powered) { - it6505_video_disable(it6505); it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, DP_SET_POWER_D3); + it6505_video_disable(it6505); } } From e6545831a17beaa724f29e79d8a12050b45da243 Mon Sep 17 00:00:00 2001 From: Douglas Anderson <dianders@chromium.org> Date: Mon, 22 Aug 2022 10:53:59 -0700 Subject: [PATCH 339/396] MAINTAINERS: Add myself as a reviewer for panel-edp.c panel-edp changes go through the drm-misc tree (as per the "DRM PANEL DRIVERS" entry in MAINTAINERS), but ever since splitting panel-edp out of panel-simple I've been trying to keep a close eye on it. Make that official by listing me as a reviewer. Signed-off-by: Douglas Anderson <dianders@chromium.org> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220822105340.1.I66a9a5577f9b0af66492ef13c47bc78ed85e5d6b@changeid --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0f9366144d31..fc62434f693f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6343,6 +6343,11 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.yaml F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +DRM DRIVER FOR GENERIC EDP PANELS +R: Douglas Anderson <dianders@chromium.org> +F: Documentation/devicetree/bindings/display/panel/panel-edp.yaml +F: drivers/gpu/drm/panel/panel-edp.c + DRM DRIVER FOR GENERIC USB DISPLAY M: Noralf Trønnes <noralf@tronnes.org> S: Maintained From 3740b081795a2e03a75a1b7573291e10378bd892 Mon Sep 17 00:00:00 2001 From: Robin Murphy <robin.murphy@arm.com> Date: Mon, 22 Aug 2022 23:01:27 +0100 Subject: [PATCH 340/396] drm/panfrost: Update io-pgtable API Convert to io-pgtable's bulk {map,unmap}_pages() APIs, to help the old single-page interfaces eventually go away. Unmapping heap BOs still wants to be done a page at a time, but everything else can get the full benefit of the more efficient interface. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Alyssa Rosenzweig <alyssa@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/daef7f8c134d989c55636a5790d8c0fcaca1bae3.1661205687.git.robin.murphy@arm.com --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 40 +++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index d3f82b26a631..963d8e1997d5 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -248,11 +248,15 @@ void panfrost_mmu_reset(struct panfrost_device *pfdev) mmu_write(pfdev, MMU_INT_MASK, ~0); } -static size_t get_pgsize(u64 addr, size_t size) +static size_t get_pgsize(u64 addr, size_t size, size_t *count) { - if (addr & (SZ_2M - 1) || size < SZ_2M) - return SZ_4K; + size_t blk_offset = -addr % SZ_2M; + if (blk_offset || size < SZ_2M) { + *count = min_not_zero(blk_offset, size) / SZ_4K; + return SZ_4K; + } + *count = size / SZ_2M; return SZ_2M; } @@ -287,12 +291,16 @@ static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, dev_dbg(pfdev->dev, "map: as=%d, iova=%llx, paddr=%lx, len=%zx", mmu->as, iova, paddr, len); while (len) { - size_t pgsize = get_pgsize(iova | paddr, len); + size_t pgcount, mapped = 0; + size_t pgsize = get_pgsize(iova | paddr, len, &pgcount); - ops->map(ops, iova, paddr, pgsize, prot, GFP_KERNEL); - iova += pgsize; - paddr += pgsize; - len -= pgsize; + ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, + GFP_KERNEL, &mapped); + /* Don't get stuck if things have gone wrong */ + mapped = max(mapped, pgsize); + iova += mapped; + paddr += mapped; + len -= mapped; } } @@ -344,15 +352,17 @@ void panfrost_mmu_unmap(struct panfrost_gem_mapping *mapping) mapping->mmu->as, iova, len); while (unmapped_len < len) { - size_t unmapped_page; - size_t pgsize = get_pgsize(iova, len - unmapped_len); + size_t unmapped_page, pgcount; + size_t pgsize = get_pgsize(iova, len - unmapped_len, &pgcount); - if (ops->iova_to_phys(ops, iova)) { - unmapped_page = ops->unmap(ops, iova, pgsize, NULL); - WARN_ON(unmapped_page != pgsize); + if (bo->is_heap) + pgcount = 1; + if (!bo->is_heap || ops->iova_to_phys(ops, iova)) { + unmapped_page = ops->unmap_pages(ops, iova, pgsize, pgcount, NULL); + WARN_ON(unmapped_page != pgsize * pgcount); } - iova += pgsize; - unmapped_len += pgsize; + iova += pgsize * pgcount; + unmapped_len += pgsize * pgcount; } panfrost_mmu_flush_range(pfdev, mapping->mmu, From 0538fa09bb1073b19b197509c51c55496091d125 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Date: Thu, 28 Jul 2022 10:40:57 +0900 Subject: [PATCH 341/396] gpu/drm/bridge/cadence: avoid flush_scheduled_work() usage Like commit c4f135d643823a86 ("workqueue: Wrap flush_workqueue() using a macro") says, flush_scheduled_work() is dangerous and will be forbidden. We are on the way for removing all flush_scheduled_work() callers from the kernel, and this patch is for removing flush_scheduled_work() call from cadence driver. Since cdns-mhdp8546 driver uses 4 works mhdp->modeset_retry_work mhdp->hpd_work mhdp->hdcp.check_work mhdp->hdcp.prop_work I assume that flush_scheduled_work() in cdns_mhdp_remove() needs to wait for only these 4 works. Since mhdp->modeset_retry_work already uses cancel_work_sync(), I assume that flush_scheduled_work() needs to wait for only 3 works. But I came to wonder whether mhdp->hdcp.check_work should be flushed or cancelled. While flush_scheduled_work() waits for completion of works which were already queued to system_wq, mhdp->hdcp.check_work is a delayed work. That is, this work won't be queued to system_wq unless timeout expires. Current code will wait for mhdp->hdcp.check_work only if timeout already expired. If timeout is not expired yet, flush_scheduled_work() will fail to cancel mhdp->hdcp.check_work, and cdns_mhdp_hdcp_check_work() which is triggered by mhdp->hdcp.check_work will schedule hdcp->check_work, which is too late for flush_scheduled_work() to wait for completion of cdns_mhdp_hdcp_prop_work(). But since I couldn't get comments on how do we want to handle this race window [1], this patch chose "do nothing" for mhdp->hdcp.check_work and mhdp->hdcp.prop_work. That is, I assume that flush_scheduled_work() in cdns_mhdp_remove() needs to wait for only mhdp->hpd_work work. Link: https://lkml.kernel.org/r/943273cb-c2ec-24e3-5edb-64eacc6e2d30@I-love.SAKURA.ne.jp [1] Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/216591bc-28bb-0453-10bb-59e268dff540@I-love.SAKURA.ne.jp --- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index ab63e7b11944..31442a922502 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2605,7 +2605,8 @@ static int cdns_mhdp_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); cancel_work_sync(&mhdp->modeset_retry_work); - flush_scheduled_work(); + flush_work(&mhdp->hpd_work); + /* Ignoring mhdp->hdcp.check_work and mhdp->hdcp.prop_work here. */ clk_disable_unprepare(mhdp->clk); From 0af02a0e52030ca0b5acc4da6d3ee3303077277c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= <michal.winiarski@intel.com> Date: Wed, 17 Aug 2022 23:12:35 +0200 Subject: [PATCH 342/396] drm/cmdline-parser: Merge negative tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Negative tests can be expressed as a single parameterized test case, which highlights that we're following the same test logic (passing invalid cmdline and expecting drm_mode_parse_command_line_for_connector to fail), which improves readability. v2: s/negative/invalid to be consistent with other testcases in DRM Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> Reviewed-by: Maíra Canal <mairacanal@riseup.net> Signed-off-by: Maíra Canal <mairacanal@riseup.net> Link: https://patchwork.freedesktop.org/patch/msgid/20220817211236.252091-1-michal.winiarski@intel.com --- .../gpu/drm/tests/drm_cmdline_parser_test.c | 293 ++++++------------ 1 file changed, 103 insertions(+), 190 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c index 59b29cdfdd35..3a46c7d6f2aa 100644 --- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c +++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c @@ -109,24 +109,6 @@ static void drm_cmdline_test_force_d_only(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF); } -static void drm_cmdline_test_margin_only(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "m"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_interlace_only(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "i"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_res(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -149,42 +131,6 @@ static void drm_cmdline_test_res(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_missing_x(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "x480"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_res_missing_y(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "1024x"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_res_bad_y(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "1024xtest"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_res_missing_y_bpp(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "1024x-24"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_res_vesa(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -274,15 +220,6 @@ static void drm_cmdline_test_res_bpp(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_bad_bpp(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480-test"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_res_refresh(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -306,15 +243,6 @@ static void drm_cmdline_test_res_refresh(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_bad_refresh(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480@refresh"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_res_bpp_refresh(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -411,15 +339,6 @@ static void drm_cmdline_test_res_bpp_refresh_force_off(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF); } -static void drm_cmdline_test_res_bpp_refresh_force_on_off(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480-24@60de"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_res_bpp_refresh_force_on(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -563,24 +482,6 @@ static void drm_cmdline_test_res_vesa_margins(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_res_invalid_mode(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480f"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_res_bpp_wrong_place_mode(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480e-24"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_name(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -608,42 +509,6 @@ static void drm_cmdline_test_name_bpp(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.bpp, 24); } -static void drm_cmdline_test_name_bpp_refresh(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "NTSC-24@60"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_name_refresh(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "NTSC@60"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_name_refresh_wrong_mode(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "NTSC@60m"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_name_refresh_invalid_mode(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "NTSC@60f"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_name_option(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -762,33 +627,6 @@ static void drm_cmdline_test_rotate_270(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_rotate_multiple(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480,rotate=0,rotate=90"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_rotate_invalid_val(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480,rotate=42"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - -static void drm_cmdline_test_rotate_truncated(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480,rotate="; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_hmirror(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -885,15 +723,6 @@ static void drm_cmdline_test_multiple_options(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } -static void drm_cmdline_test_invalid_option(struct kunit *test) -{ - struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480,test=42"; - - KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline, - &no_connector, &mode)); -} - static void drm_cmdline_test_bpp_extra_and_option(struct kunit *test) { struct drm_cmdline_mode mode = { }; @@ -1006,64 +835,148 @@ static void drm_cmdline_test_panel_orientation(struct kunit *test) KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); } +struct drm_cmdline_invalid_test { + const char *name; + const char *cmdline; +}; + +static void drm_cmdline_test_invalid(struct kunit *test) +{ + const struct drm_cmdline_invalid_test *params = test->param_value; + struct drm_cmdline_mode mode = { }; + + KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(params->cmdline, + &no_connector, + &mode)); +} + +static const struct drm_cmdline_invalid_test drm_cmdline_invalid_tests[] = { + { + .name = "margin_only", + .cmdline = "m", + }, + { + .name = "interlace_only", + .cmdline = "i", + }, + { + .name = "res_missing_x", + .cmdline = "x480", + }, + { + .name = "res_missing_y", + .cmdline = "1024x", + }, + { + .name = "res_bad_y", + .cmdline = "1024xtest", + }, + { + .name = "res_missing_y_bpp", + .cmdline = "1024x-24", + }, + { + .name = "res_bad_bpp", + .cmdline = "720x480-test", + }, + { + .name = "res_bad_refresh", + .cmdline = "720x480@refresh", + }, + { + .name = "res_bpp_refresh_force_on_off", + .cmdline = "720x480-24@60de", + }, + { + .name = "res_invalid_mode", + .cmdline = "720x480f", + }, + { + .name = "res_bpp_wrong_place_mode", + .cmdline = "720x480e-24", + }, + { + .name = "name_bpp_refresh", + .cmdline = "NTSC-24@60", + }, + { + .name = "name_refresh", + .cmdline = "NTSC@60", + }, + { + .name = "name_refresh_wrong_mode", + .cmdline = "NTSC@60m", + }, + { + .name = "name_refresh_invalid_mode", + .cmdline = "NTSC@60f", + }, + { + .name = "rotate_multiple", + .cmdline = "720x480,rotate=0,rotate=90", + }, + { + .name = "rotate_invalid_val", + .cmdline = "720x480,rotate=42", + }, + { + .name = "rotate_truncated", + .cmdline = "720x480,rotate=", + }, + { + .name = "invalid_option", + .cmdline = "720x480,test=42", + }, +}; + +static void drm_cmdline_invalid_desc(const struct drm_cmdline_invalid_test *t, + char *desc) +{ + sprintf(desc, "%s", t->name); +} + +KUNIT_ARRAY_PARAM(drm_cmdline_invalid, drm_cmdline_invalid_tests, drm_cmdline_invalid_desc); + static struct kunit_case drm_cmdline_parser_tests[] = { KUNIT_CASE(drm_cmdline_test_force_d_only), KUNIT_CASE(drm_cmdline_test_force_D_only_dvi), KUNIT_CASE(drm_cmdline_test_force_D_only_hdmi), KUNIT_CASE(drm_cmdline_test_force_D_only_not_digital), KUNIT_CASE(drm_cmdline_test_force_e_only), - KUNIT_CASE(drm_cmdline_test_margin_only), - KUNIT_CASE(drm_cmdline_test_interlace_only), KUNIT_CASE(drm_cmdline_test_res), - KUNIT_CASE(drm_cmdline_test_res_missing_x), - KUNIT_CASE(drm_cmdline_test_res_missing_y), - KUNIT_CASE(drm_cmdline_test_res_bad_y), - KUNIT_CASE(drm_cmdline_test_res_missing_y_bpp), KUNIT_CASE(drm_cmdline_test_res_vesa), KUNIT_CASE(drm_cmdline_test_res_vesa_rblank), KUNIT_CASE(drm_cmdline_test_res_rblank), KUNIT_CASE(drm_cmdline_test_res_bpp), - KUNIT_CASE(drm_cmdline_test_res_bad_bpp), KUNIT_CASE(drm_cmdline_test_res_refresh), - KUNIT_CASE(drm_cmdline_test_res_bad_refresh), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_margins), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_off), - KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_off), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_analog), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_digital), KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on), KUNIT_CASE(drm_cmdline_test_res_margins_force_on), KUNIT_CASE(drm_cmdline_test_res_vesa_margins), - KUNIT_CASE(drm_cmdline_test_res_invalid_mode), - KUNIT_CASE(drm_cmdline_test_res_bpp_wrong_place_mode), KUNIT_CASE(drm_cmdline_test_name), KUNIT_CASE(drm_cmdline_test_name_bpp), - KUNIT_CASE(drm_cmdline_test_name_refresh), - KUNIT_CASE(drm_cmdline_test_name_bpp_refresh), - KUNIT_CASE(drm_cmdline_test_name_refresh_wrong_mode), - KUNIT_CASE(drm_cmdline_test_name_refresh_invalid_mode), KUNIT_CASE(drm_cmdline_test_name_option), KUNIT_CASE(drm_cmdline_test_name_bpp_option), KUNIT_CASE(drm_cmdline_test_rotate_0), KUNIT_CASE(drm_cmdline_test_rotate_90), KUNIT_CASE(drm_cmdline_test_rotate_180), KUNIT_CASE(drm_cmdline_test_rotate_270), - KUNIT_CASE(drm_cmdline_test_rotate_multiple), - KUNIT_CASE(drm_cmdline_test_rotate_invalid_val), - KUNIT_CASE(drm_cmdline_test_rotate_truncated), KUNIT_CASE(drm_cmdline_test_hmirror), KUNIT_CASE(drm_cmdline_test_vmirror), KUNIT_CASE(drm_cmdline_test_margin_options), KUNIT_CASE(drm_cmdline_test_multiple_options), - KUNIT_CASE(drm_cmdline_test_invalid_option), KUNIT_CASE(drm_cmdline_test_bpp_extra_and_option), KUNIT_CASE(drm_cmdline_test_extra_and_option), KUNIT_CASE(drm_cmdline_test_freestanding_options), KUNIT_CASE(drm_cmdline_test_freestanding_force_e_and_options), KUNIT_CASE(drm_cmdline_test_panel_orientation), + KUNIT_CASE_PARAM(drm_cmdline_test_invalid, drm_cmdline_invalid_gen_params), {} }; From 169a32b76842c10fbe532cde6cc25e89bbf54341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= <michal.winiarski@intel.com> Date: Wed, 17 Aug 2022 23:12:36 +0200 Subject: [PATCH 343/396] drm/cmdline-parser: Use assert when needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expecting to observe a specific value, when the function responsible for setting the value has failed will lead to extra noise in test output. Use assert when the situation calls for it. Also - very small tidying up around the changed areas (whitespace). v2: Leave out the locals (drm_connector is huge) (lkp) Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> Reviewed-by: Maíra Canal <mairacanal@riseup.net> Signed-off-by: Maíra Canal <mairacanal@riseup.net> Link: https://patchwork.freedesktop.org/patch/msgid/20220817211236.252091-2-michal.winiarski@intel.com --- .../gpu/drm/tests/drm_cmdline_parser_test.c | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c index 3a46c7d6f2aa..09b806e27506 100644 --- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c +++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c @@ -16,7 +16,7 @@ static void drm_cmdline_test_force_e_only(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "e"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -34,7 +34,7 @@ static void drm_cmdline_test_force_D_only_not_digital(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "D"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -56,7 +56,7 @@ static void drm_cmdline_test_force_D_only_hdmi(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "D"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &connector_hdmi, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -78,7 +78,7 @@ static void drm_cmdline_test_force_D_only_dvi(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "D"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &connector_dvi, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -96,7 +96,7 @@ static void drm_cmdline_test_force_d_only(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "d"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -114,7 +114,7 @@ static void drm_cmdline_test_res(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -136,7 +136,7 @@ static void drm_cmdline_test_res_vesa(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480M"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -158,7 +158,7 @@ static void drm_cmdline_test_res_vesa_rblank(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480MR"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -180,7 +180,7 @@ static void drm_cmdline_test_res_rblank(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480R"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -202,7 +202,7 @@ static void drm_cmdline_test_res_bpp(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -225,7 +225,7 @@ static void drm_cmdline_test_res_refresh(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480@60"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -248,7 +248,7 @@ static void drm_cmdline_test_res_bpp_refresh(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -272,7 +272,7 @@ static void drm_cmdline_test_res_bpp_refresh_interlaced(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60i"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -294,9 +294,9 @@ static void drm_cmdline_test_res_bpp_refresh_interlaced(struct kunit *test) static void drm_cmdline_test_res_bpp_refresh_margins(struct kunit *test) { struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480-24@60m"; + const char *cmdline = "720x480-24@60m"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -318,9 +318,9 @@ static void drm_cmdline_test_res_bpp_refresh_margins(struct kunit *test) static void drm_cmdline_test_res_bpp_refresh_force_off(struct kunit *test) { struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480-24@60d"; + const char *cmdline = "720x480-24@60d"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -342,9 +342,9 @@ static void drm_cmdline_test_res_bpp_refresh_force_off(struct kunit *test) static void drm_cmdline_test_res_bpp_refresh_force_on(struct kunit *test) { struct drm_cmdline_mode mode = { }; - const char *cmdline = "720x480-24@60e"; + const char *cmdline = "720x480-24@60e"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -368,7 +368,7 @@ static void drm_cmdline_test_res_bpp_refresh_force_on_analog(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24@60D"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -395,7 +395,7 @@ static void drm_cmdline_test_res_bpp_refresh_force_on_digital(struct kunit *test }; const char *cmdline = "720x480-24@60D"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -443,7 +443,7 @@ static void drm_cmdline_test_res_margins_force_on(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480me"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -465,7 +465,7 @@ static void drm_cmdline_test_res_vesa_margins(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480Mm"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -487,7 +487,7 @@ static void drm_cmdline_test_name(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -499,7 +499,7 @@ static void drm_cmdline_test_name_bpp(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC-24"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); @@ -514,7 +514,7 @@ static void drm_cmdline_test_name_option(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC,rotate=180"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); @@ -526,7 +526,7 @@ static void drm_cmdline_test_name_bpp_option(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "NTSC-24,rotate=180"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_STREQ(test, mode.name, "NTSC"); @@ -540,7 +540,7 @@ static void drm_cmdline_test_rotate_0(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=0"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -563,7 +563,7 @@ static void drm_cmdline_test_rotate_90(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=90"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -586,7 +586,7 @@ static void drm_cmdline_test_rotate_180(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=180"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -609,7 +609,7 @@ static void drm_cmdline_test_rotate_270(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=270"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -632,7 +632,7 @@ static void drm_cmdline_test_hmirror(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,reflect_x"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -655,7 +655,7 @@ static void drm_cmdline_test_vmirror(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,reflect_y"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -679,7 +679,7 @@ static void drm_cmdline_test_margin_options(struct kunit *test) const char *cmdline = "720x480,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -705,7 +705,7 @@ static void drm_cmdline_test_multiple_options(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480,rotate=270,reflect_x"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -728,7 +728,7 @@ static void drm_cmdline_test_bpp_extra_and_option(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480-24e,rotate=180"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -752,7 +752,7 @@ static void drm_cmdline_test_extra_and_option(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "720x480e,rotate=180"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_TRUE(test, mode.specified); KUNIT_EXPECT_EQ(test, mode.xres, 720); @@ -774,7 +774,7 @@ static void drm_cmdline_test_freestanding_options(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -797,7 +797,7 @@ static void drm_cmdline_test_freestanding_force_e_and_options(struct kunit *test struct drm_cmdline_mode mode = { }; const char *cmdline = "e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); @@ -820,7 +820,7 @@ static void drm_cmdline_test_panel_orientation(struct kunit *test) struct drm_cmdline_mode mode = { }; const char *cmdline = "panel_orientation=upside_down"; - KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, &no_connector, &mode)); KUNIT_EXPECT_FALSE(test, mode.specified); KUNIT_EXPECT_FALSE(test, mode.refresh_specified); From e06a46087d8bbde7ca31361789edfe026b08fdce Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@intel.com> Date: Thu, 1 Sep 2022 19:19:33 +0300 Subject: [PATCH 344/396] drm/i915/dp_mst: Fix mst_mgr lookup during atomic check If an MST connector was disabled in the old state during a commit, the connector's best_encoder will be NULL, so we can't look up mst_mgr via it. Do the lookup instead via intel_connector->mst_port which always points to the primary encoder. This fixes the following: [ 58.922866] BUG: kernel NULL pointer dereference, address: 0000000000000170 [ 58.922867] #PF: supervisor read access in kernel mode [ 58.922868] #PF: error_code(0x0000) - not-present page [ 58.922869] PGD 0 P4D 0 [ 58.922870] Oops: 0000 [#1] PREEMPT SMP NOPTI [ 58.922872] CPU: 0 PID: 133 Comm: kworker/0:2 Tainted: G U 6.0.0-rc3-imre+ #560 [ 58.922874] Hardware name: Intel Corporation Alder Lake Client Platform/AlderLake-P DDR5 RVP, BIOS ADLPFWI1.R00.3135.A00.2203251419 03/25/2022 [ 58.922874] Workqueue: events output_poll_execute [drm_kms_helper] [ 58.922879] RIP: 0010:intel_dp_mst_atomic_check+0xbb/0x1c0 [i915] [ 58.922955] Code: 5b 7b f6 ff 84 c0 75 41 48 8b 44 24 18 65 48 2b 04 25 28 00 00 00 0f 85 ff 00 00 00 48 8b 45 10 48 8b 93 10 07 00 00 4c 89 e7 <48> 8b b0 70 01 00 00 48 83 c4 20 5b 5d 48 81 c6 f0 0c 00 00 41 5c [ 58.922956] RSP: 0018:ffffc90000633a88 EFLAGS: 00010246 [ 58.922957] RAX: 0000000000000000 RBX: ffff888117d19000 RCX: ffff888101893308 [ 58.922958] RDX: ffff888122981000 RSI: ffffffff82309ecc RDI: ffff888114da6800 [ 58.922959] RBP: ffff8881094bab48 R08: 0000000081917436 R09: 0000000068191743 [ 58.922960] R10: 0000000000000001 R11: 0000000000000001 R12: ffff888114da6800 [ 58.922960] R13: ffff8881143f8000 R14: 0000000000000000 R15: ffff888119bf2000 [ 58.922961] FS: 0000000000000000(0000) GS:ffff888496200000(0000) knlGS:0000000000000000 [ 58.922962] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 58.922962] CR2: 0000000000000170 CR3: 0000000005612004 CR4: 0000000000770ef0 [ 58.922963] PKRU: 55555554 [ 58.922963] Call Trace: [ 58.922964] <TASK> [ 58.922966] drm_atomic_helper_check_modeset+0x3f8/0xc70 [drm_kms_helper] [ 58.922972] intel_atomic_check+0xb1/0x3180 [i915] [ 58.923059] ? find_held_lock+0x2b/0x80 [ 58.923064] drm_atomic_check_only+0x5d3/0xa60 [drm] [ 58.923082] drm_atomic_commit+0x56/0xc0 [drm] [ 58.923097] ? drm_plane_get_damage_clips.cold+0x1c/0x1c [drm] [ 58.923114] drm_client_modeset_commit_atomic+0x235/0x280 [drm] [ 58.923132] drm_client_modeset_commit_locked+0x5b/0x190 [drm] [ 58.923148] drm_client_modeset_commit+0x24/0x50 [drm] [ 58.923164] drm_fb_helper_set_par+0xae/0xe0 [drm_kms_helper] [ 58.923171] drm_fb_helper_hotplug_event+0xd5/0xf0 [drm_kms_helper] [ 58.923178] output_poll_execute+0xac/0x200 [drm_kms_helper] [ 58.923187] process_one_work+0x268/0x580 [ 58.923190] ? process_one_work+0x580/0x580 [ 58.923191] worker_thread+0x52/0x3b0 [ 58.923193] ? process_one_work+0x580/0x580 [ 58.923195] kthread+0xf0/0x120 [ 58.923196] ? kthread_complete_and_exit+0x20/0x20 [ 58.923198] ret_from_fork+0x1f/0x30 [ 58.923202] </TASK> Fixes: ffac9721939d ("drm/display/dp_mst: Don't open code modeset checks for releasing time slots") Cc: Lyude Paul <lyude@redhat.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901161933.1004778-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 13abe2b2170e..7713c19042f3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -315,11 +315,8 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, struct drm_atomic_state *_state) { struct intel_atomic_state *state = to_intel_atomic_state(_state); - struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(&state->base, connector); struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_dp_mst_topology_mgr *mgr; int ret; ret = intel_digital_connector_atomic_check(connector, &state->base); @@ -330,8 +327,9 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, if (ret) return ret; - mgr = &enc_to_mst(to_intel_encoder(old_conn_state->best_encoder))->primary->dp.mst_mgr; - return drm_dp_atomic_release_time_slots(&state->base, mgr, intel_connector->port); + return drm_dp_atomic_release_time_slots(&state->base, + &intel_connector->mst_port->mst_mgr, + intel_connector->port); } static void clear_act_sent(struct intel_encoder *encoder, From 3fc307dcec8b9aeecae8c1bf2c97f770805daf4e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com> Date: Wed, 31 Aug 2022 11:26:51 +0300 Subject: [PATCH 345/396] drm/bridge: ti-sn65dsi86: Reject modes with too large blanking The front and back porch registers are 8 bits, and pulse width registers are 15 bits, so reject any modes with larger periods. Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220831082653.20449-2-tomi.valkeinen@ideasonboard.com --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 90bbabde1595..09d3c65fa2ba 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -747,6 +747,29 @@ ti_sn_bridge_mode_valid(struct drm_bridge *bridge, if (mode->clock > 594000) return MODE_CLOCK_HIGH; + /* + * The front and back porch registers are 8 bits, and pulse width + * registers are 15 bits, so reject any modes with larger periods. + */ + + if ((mode->hsync_start - mode->hdisplay) > 0xff) + return MODE_HBLANK_WIDE; + + if ((mode->vsync_start - mode->vdisplay) > 0xff) + return MODE_VBLANK_WIDE; + + if ((mode->hsync_end - mode->hsync_start) > 0x7fff) + return MODE_HSYNC_WIDE; + + if ((mode->vsync_end - mode->vsync_start) > 0x7fff) + return MODE_VSYNC_WIDE; + + if ((mode->htotal - mode->hsync_end) > 0xff) + return MODE_HBLANK_WIDE; + + if ((mode->vtotal - mode->vsync_end) > 0xff) + return MODE_VBLANK_WIDE; + return MODE_OK; } From e43d5864f36ab32f831b1af7bc2171031e58e2ac Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Date: Wed, 31 Aug 2022 11:26:52 +0300 Subject: [PATCH 346/396] drm/bridge: ti-sn65dsi86: Support DisplayPort (non-eDP) mode Despite the SN65DSI86 being an eDP bridge, on some systems its output is routed to a DisplayPort connector. Enable DisplayPort mode when the next component in the display pipeline is detected as a DisplayPort connector, and disable eDP features in that case. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reworked to set bridge type based on the next bridge/connector. Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com> -- Changes since v1/RFC: - Rebased on top of "drm/bridge: ti-sn65dsi86: switch to devm_drm_of_get_bridge" - eDP/DP mode determined from the next bridge connector type. Changes since v2: - Remove setting of Standard DP Scrambler Seed. (It's read-only). - Prevent setting DP_EDP_CONFIGURATION_SET in ti_sn_bridge_atomic_enable() - Use Doug's suggested text for disabling ASSR on DP mode. Changes since v3: - Remove ASSR_CONTROL definition Changes since v4: - Refactor code to configure the DP/eDP scrambler in one place. Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220831082653.20449-3-tomi.valkeinen@ideasonboard.com --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 09d3c65fa2ba..6e053e2af229 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -92,6 +92,8 @@ #define SN_DATARATE_CONFIG_REG 0x94 #define DP_DATARATE_MASK GENMASK(7, 5) #define DP_DATARATE(x) ((x) << 5) +#define SN_TRAINING_SETTING_REG 0x95 +#define SCRAMBLE_DISABLE BIT(4) #define SN_ML_TX_MODE_REG 0x96 #define ML_TX_MAIN_LINK_OFF 0 #define ML_TX_NORMAL_MODE BIT(0) @@ -1070,12 +1072,23 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge, /* * The SN65DSI86 only supports ASSR Display Authentication method and - * this method is enabled by default. An eDP panel must support this + * this method is enabled for eDP panels. An eDP panel must support this * authentication method. We need to enable this method in the eDP panel * at DisplayPort address 0x0010A prior to link training. + * + * As only ASSR is supported by SN65DSI86, for full DisplayPort displays + * we need to disable the scrambler. */ - drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET, - DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); + if (pdata->bridge.type == DRM_MODE_CONNECTOR_eDP) { + drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET, + DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); + + regmap_update_bits(pdata->regmap, SN_TRAINING_SETTING_REG, + SCRAMBLE_DISABLE, 0); + } else { + regmap_update_bits(pdata->regmap, SN_TRAINING_SETTING_REG, + SCRAMBLE_DISABLE, SCRAMBLE_DISABLE); + } bpp = ti_sn_bridge_get_bpp(connector); /* Set the DP output format (18 bpp or 24 bpp) */ @@ -1241,6 +1254,8 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.funcs = &ti_sn_bridge_funcs; pdata->bridge.of_node = np; + pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort + ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; drm_bridge_add(&pdata->bridge); From c312b0df3b13e4c533743bb2c37fd1bc237368e5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Date: Wed, 31 Aug 2022 11:26:53 +0300 Subject: [PATCH 347/396] drm/bridge: ti-sn65dsi86: Implement bridge connector operations for DP Implement the bridge connector-related .get_edid() and .detect() operations for full DP mode, and report the related bridge capabilities and type. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220831082653.20449-4-tomi.valkeinen@ideasonboard.com --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 6e053e2af229..3c3561942eb6 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -29,6 +29,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_bridge_connector.h> +#include <drm/drm_edid.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> @@ -68,6 +69,7 @@ #define BPP_18_RGB BIT(0) #define SN_HPD_DISABLE_REG 0x5C #define HPD_DISABLE BIT(0) +#define HPD_DEBOUNCED_STATE BIT(4) #define SN_GPIO_IO_REG 0x5E #define SN_GPIO_INPUT_SHIFT 4 #define SN_GPIO_OUTPUT_SHIFT 0 @@ -1158,10 +1160,33 @@ static void ti_sn_bridge_atomic_post_disable(struct drm_bridge *bridge, pm_runtime_put_sync(pdata->dev); } +static enum drm_connector_status ti_sn_bridge_detect(struct drm_bridge *bridge) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + int val = 0; + + pm_runtime_get_sync(pdata->dev); + regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val); + pm_runtime_put_autosuspend(pdata->dev); + + return val & HPD_DEBOUNCED_STATE ? connector_status_connected + : connector_status_disconnected; +} + +static struct edid *ti_sn_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + + return drm_get_edid(connector, &pdata->aux.ddc); +} + static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .attach = ti_sn_bridge_attach, .detach = ti_sn_bridge_detach, .mode_valid = ti_sn_bridge_mode_valid, + .get_edid = ti_sn_bridge_get_edid, + .detect = ti_sn_bridge_detect, .atomic_pre_enable = ti_sn_bridge_atomic_pre_enable, .atomic_enable = ti_sn_bridge_atomic_enable, .atomic_disable = ti_sn_bridge_atomic_disable, @@ -1257,6 +1282,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; + if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT; + drm_bridge_add(&pdata->bridge); ret = ti_sn_attach_host(pdata); From a4be71430c76eca43679e8485085c230afa84460 Mon Sep 17 00:00:00 2001 From: Chris Morgan <macromorgan@hotmail.com> Date: Fri, 2 Sep 2022 10:39:05 -0500 Subject: [PATCH 348/396] dt-bindings: Add byteswap order to chrontel ch7033 Update dt-binding documentation to add support for setting byteswap of chrontel ch7033. New property name of chrontel,byteswap added to set the byteswap order. This property is optional. Signed-off-by: Chris Morgan <macromorgan@hotmail.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220902153906.31000-2-macroalpha82@gmail.com --- .../bindings/display/bridge/chrontel,ch7033.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml b/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml index bb6289c7d375..984b90893583 100644 --- a/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml +++ b/Documentation/devicetree/bindings/display/bridge/chrontel,ch7033.yaml @@ -14,6 +14,19 @@ properties: compatible: const: chrontel,ch7033 + chrontel,byteswap: + $ref: /schemas/types.yaml#/definitions/uint8 + enum: + - 0 # BYTE_SWAP_RGB + - 1 # BYTE_SWAP_RBG + - 2 # BYTE_SWAP_GRB + - 3 # BYTE_SWAP_GBR + - 4 # BYTE_SWAP_BRG + - 5 # BYTE_SWAP_BGR + description: | + Set the byteswap value of the bridge. This is optional and if not + set value of BYTE_SWAP_BGR is used. + reg: maxItems: 1 description: I2C address of the device From ce9564cfc9aea65e68eb343c599317633bc2321a Mon Sep 17 00:00:00 2001 From: Chris Morgan <macromorgan@hotmail.com> Date: Fri, 2 Sep 2022 10:39:06 -0500 Subject: [PATCH 349/396] drm/bridge: chrontel-ch7033: Add byteswap order setting Add the option to set the byteswap order in the devicetree. For the official HDMI DIP for the NTC CHIP the byteswap order needs to be RGB, however the driver sets it as BGR. With this patch the driver will remain at BGR unless manually specified via devicetree. Signed-off-by: Chris Morgan <macromorgan@hotmail.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220902153906.31000-3-macroalpha82@gmail.com --- drivers/gpu/drm/bridge/chrontel-ch7033.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c index ba060277c3fd..c5719908ce2d 100644 --- a/drivers/gpu/drm/bridge/chrontel-ch7033.c +++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c @@ -68,6 +68,7 @@ enum { BYTE_SWAP_GBR = 3, BYTE_SWAP_BRG = 4, BYTE_SWAP_BGR = 5, + BYTE_SWAP_MAX = 6, }; /* Page 0, Register 0x19 */ @@ -355,6 +356,8 @@ static void ch7033_bridge_mode_set(struct drm_bridge *bridge, int hsynclen = mode->hsync_end - mode->hsync_start; int vbporch = mode->vsync_start - mode->vdisplay; int vsynclen = mode->vsync_end - mode->vsync_start; + u8 byte_swap; + int ret; /* * Page 4 @@ -398,8 +401,16 @@ static void ch7033_bridge_mode_set(struct drm_bridge *bridge, regmap_write(priv->regmap, 0x15, vbporch); regmap_write(priv->regmap, 0x16, vsynclen); - /* Input color swap. */ - regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR); + /* Input color swap. Byte order is optional and will default to + * BYTE_SWAP_BGR to preserve backwards compatibility with existing + * driver. + */ + ret = of_property_read_u8(priv->bridge.of_node, "chrontel,byteswap", + &byte_swap); + if (!ret && byte_swap < BYTE_SWAP_MAX) + regmap_update_bits(priv->regmap, 0x18, SWAP, byte_swap); + else + regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR); /* Input clock and sync polarity. */ regmap_update_bits(priv->regmap, 0x19, 0x1, mode->clock >> 16); From a2ce58e8f9e4cef389a04077d052f8135f380c5c Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann <msp@baylibre.com> Date: Thu, 1 Sep 2022 12:41:40 +0800 Subject: [PATCH 350/396] dt-bindings: mediatek,dp: Add Display Port binding This controller is present on several mediatek hardware. Currently mt8195 and mt8395 have this controller without a functional difference, so only one compatible field is added. The controller can have two forms, as a normal display port and as an embedded display port. Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: Rob Herring <robh@kernel.org> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-2-rex-bc.chen@mediatek.com --- .../display/mediatek/mediatek,dp.yaml | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml new file mode 100644 index 000000000000..ff781f2174a0 --- /dev/null +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml @@ -0,0 +1,116 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/mediatek/mediatek,dp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek Display Port Controller + +maintainers: + - Chun-Kuang Hu <chunkuang.hu@kernel.org> + - Jitao shi <jitao.shi@mediatek.com> + +description: | + MediaTek DP and eDP are different hardwares and there are some features + which are not supported for eDP. For example, audio is not supported for + eDP. Therefore, we need to use two different compatibles to describe them. + In addition, We just need to enable the power domain of DP, so the clock + of DP is generated by itself and we are not using other PLL to generate + clocks. + +properties: + compatible: + enum: + - mediatek,mt8195-dp-tx + - mediatek,mt8195-edp-tx + + reg: + maxItems: 1 + + nvmem-cells: + maxItems: 1 + description: efuse data for display port calibration + + nvmem-cell-names: + const: dp_calibration_data + + power-domains: + maxItems: 1 + + interrupts: + maxItems: 1 + + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Input endpoint of the controller, usually dp_intf + + port@1: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: Output endpoint of the controller + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + properties: + data-lanes: + description: | + number of lanes supported by the hardware. + The possible values: + 0 - For 1 lane enabled in IP. + 0 1 - For 2 lanes enabled in IP. + 0 1 2 3 - For 4 lanes enabled in IP. + minItems: 1 + maxItems: 4 + required: + - data-lanes + + required: + - port@0 + - port@1 + + max-linkrate-mhz: + enum: [ 1620, 2700, 5400, 8100 ] + description: maximum link rate supported by the hardware. + +required: + - compatible + - reg + - interrupts + - ports + - max-linkrate-mhz + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/mt8195-power.h> + dptx@1c600000 { + compatible = "mediatek,mt8195-dp-tx"; + reg = <0x1c600000 0x8000>; + power-domains = <&spm MT8195_POWER_DOMAIN_DP_TX>; + interrupts = <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH 0>; + max-linkrate-mhz = <8100>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dptx_in: endpoint { + remote-endpoint = <&dp_intf0_out>; + }; + }; + port@1 { + reg = <1>; + dptx_out: endpoint { + data-lanes = <0 1 2 3>; + }; + }; + }; + }; From f89aa0b6db18dea3c3c8ef266cc6c9fd8dff2d72 Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann <msp@baylibre.com> Date: Thu, 1 Sep 2022 12:41:41 +0800 Subject: [PATCH 351/396] video/hdmi: Add audio_infoframe packing for DP Similar to HDMI, DP uses audio infoframes as well which are structured very similar to the HDMI ones. This patch adds a helper function to pack the HDMI audio infoframe for DP, called hdmi_audio_infoframe_pack_for_dp(). hdmi_audio_infoframe_pack_only() is split into two parts. One of them packs the payload only and can be used for HDMI and DP. Also constify the frame parameter in hdmi_audio_infoframe_check() as it is passed to hdmi_audio_infoframe_check_only() which expects a const. Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-3-rex-bc.chen@mediatek.com --- drivers/video/hdmi.c | 82 +++++++++++++++++++++++++++--------- include/drm/display/drm_dp.h | 2 + include/linux/hdmi.h | 7 ++- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 947be761dfa4..03c7f27dde49 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include <drm/display/drm_dp.h> #include <linux/bitops.h> #include <linux/bug.h> #include <linux/errno.h> @@ -381,12 +382,34 @@ static int hdmi_audio_infoframe_check_only(const struct hdmi_audio_infoframe *fr * * Returns 0 on success or a negative error code on failure. */ -int hdmi_audio_infoframe_check(struct hdmi_audio_infoframe *frame) +int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame) { return hdmi_audio_infoframe_check_only(frame); } EXPORT_SYMBOL(hdmi_audio_infoframe_check); +static void +hdmi_audio_infoframe_pack_payload(const struct hdmi_audio_infoframe *frame, + u8 *buffer) +{ + u8 channels; + + if (frame->channels >= 2) + channels = frame->channels - 1; + else + channels = 0; + + buffer[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7); + buffer[1] = ((frame->sample_frequency & 0x7) << 2) | + (frame->sample_size & 0x3); + buffer[2] = frame->coding_type_ext & 0x1f; + buffer[3] = frame->channel_allocation; + buffer[4] = (frame->level_shift_value & 0xf) << 3; + + if (frame->downmix_inhibit) + buffer[4] |= BIT(7); +} + /** * hdmi_audio_infoframe_pack_only() - write HDMI audio infoframe to binary buffer * @frame: HDMI audio infoframe @@ -404,7 +427,6 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_check); ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, void *buffer, size_t size) { - unsigned char channels; u8 *ptr = buffer; size_t length; int ret; @@ -420,28 +442,13 @@ ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, memset(buffer, 0, size); - if (frame->channels >= 2) - channels = frame->channels - 1; - else - channels = 0; - ptr[0] = frame->type; ptr[1] = frame->version; ptr[2] = frame->length; ptr[3] = 0; /* checksum */ - /* start infoframe payload */ - ptr += HDMI_INFOFRAME_HEADER_SIZE; - - ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7); - ptr[1] = ((frame->sample_frequency & 0x7) << 2) | - (frame->sample_size & 0x3); - ptr[2] = frame->coding_type_ext & 0x1f; - ptr[3] = frame->channel_allocation; - ptr[4] = (frame->level_shift_value & 0xf) << 3; - - if (frame->downmix_inhibit) - ptr[4] |= BIT(7); + hdmi_audio_infoframe_pack_payload(frame, + ptr + HDMI_INFOFRAME_HEADER_SIZE); hdmi_infoframe_set_checksum(buffer, length); @@ -479,6 +486,43 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, } EXPORT_SYMBOL(hdmi_audio_infoframe_pack); +/** + * hdmi_audio_infoframe_pack_for_dp - Pack a HDMI Audio infoframe for DisplayPort + * + * @frame: HDMI Audio infoframe + * @sdp: Secondary data packet for DisplayPort. + * @dp_version: DisplayPort version to be encoded in the header + * + * Packs a HDMI Audio Infoframe to be sent over DisplayPort. This function + * fills the secondary data packet to be used for DisplayPort. + * + * Return: Number of total written bytes or a negative errno on failure. + */ +ssize_t +hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame, + struct dp_sdp *sdp, u8 dp_version) +{ + int ret; + + ret = hdmi_audio_infoframe_check(frame); + if (ret) + return ret; + + memset(sdp->db, 0, sizeof(sdp->db)); + + /* Secondary-data packet header */ + sdp->sdp_header.HB0 = 0; + sdp->sdp_header.HB1 = frame->type; + sdp->sdp_header.HB2 = DP_SDP_AUDIO_INFOFRAME_HB2; + sdp->sdp_header.HB3 = (dp_version & 0x3f) << 2; + + hdmi_audio_infoframe_pack_payload(frame, sdp->db); + + /* Return size = frame length + four HB for sdp_header */ + return frame->length + 4; +} +EXPORT_SYMBOL(hdmi_audio_infoframe_pack_for_dp); + /** * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe * @frame: HDMI vendor infoframe diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index 9e3aff7e68bb..6c0871164771 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -1536,6 +1536,8 @@ enum drm_dp_phy { #define DP_SDP_VSC_EXT_CEA 0x21 /* DP 1.4 */ /* 0x80+ CEA-861 infoframe types */ +#define DP_SDP_AUDIO_INFOFRAME_HB2 0x1b + /** * struct dp_sdp_header - DP secondary data packet header * @HB0: Secondary Data Packet ID diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index c8ec982ff498..2f4dcc8d060e 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -336,7 +336,12 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, void *buffer, size_t size); ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, void *buffer, size_t size); -int hdmi_audio_infoframe_check(struct hdmi_audio_infoframe *frame); +int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame); + +struct dp_sdp; +ssize_t +hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame, + struct dp_sdp *sdp, u8 dp_version); enum hdmi_3d_structure { HDMI_3D_STRUCTURE_INVALID = -1, From f70ac097a2cf5d4b67b2c1bbb73196c573ffcb7b Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann <msp@baylibre.com> Date: Thu, 1 Sep 2022 12:41:42 +0800 Subject: [PATCH 352/396] drm/mediatek: Add MT8195 Embedded DisplayPort driver This patch adds a embedded displayport driver for the MediaTek mt8195 SoC. It supports the MT8195, the embedded DisplayPort units. It offers DisplayPort 1.4 with up to 4 lanes. The driver creates a child device for the phy. The child device will never exist without the parent being active. As they are sharing a register range, the parent passes a regmap pointer to the child so that both can work with the same register range. The phy driver sets device data that is read by the parent to get the phy device that can be used to control the phy properties. This driver is based on an initial version by Jitao shi <jitao.shi@mediatek.com> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-4-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/Kconfig | 9 + drivers/gpu/drm/mediatek/Makefile | 2 + drivers/gpu/drm/mediatek/mtk_dp.c | 1999 +++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_dp_reg.h | 305 ++++ 4 files changed, 2315 insertions(+) create mode 100644 drivers/gpu/drm/mediatek/mtk_dp.c create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_reg.h diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 6d7d0e207082..369e495d0c3e 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -21,6 +21,15 @@ config DRM_MEDIATEK This driver provides kernel mode setting and buffer management to userspace. +config DRM_MEDIATEK_DP + tristate "DRM DPTX Support for MediaTek SoCs" + depends on DRM_MEDIATEK + select PHY_MTK_DP + select DRM_DISPLAY_HELPER + select DRM_DISPLAY_DP_HELPER + help + DRM/KMS Display Port driver for MediaTek SoCs. + config DRM_MEDIATEK_HDMI tristate "DRM HDMI Support for Mediatek SoCs" depends on DRM_MEDIATEK diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index 6e604a933ed0..3517d1c65cd7 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -23,3 +23,5 @@ mediatek-drm-hdmi-objs := mtk_cec.o \ mtk_hdmi_ddc.o obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o + +obj-$(CONFIG_DRM_MEDIATEK_DP) += mtk_dp.o diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c new file mode 100644 index 000000000000..e2ec9b02b1aa --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -0,0 +1,1999 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019-2022 MediaTek Inc. + * Copyright (c) 2022 BayLibre + */ + +#include <drm/display/drm_dp.h> +#include <drm/display/drm_dp_helper.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_crtc.h> +#include <drm/drm_edid.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> +#include <linux/arm-smccc.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/media-bus-format.h> +#include <linux/nvmem-consumer.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/soc/mediatek/mtk_sip_svc.h> +#include <video/videomode.h> + +#include "mtk_dp_reg.h" + +#define MTK_DP_SIP_CONTROL_AARCH32 MTK_SIP_SMC_CMD(0x523) +#define MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE (BIT(0) | BIT(5)) + +#define MTK_DP_THREAD_CABLE_STATE_CHG BIT(0) +#define MTK_DP_THREAD_HPD_EVENT BIT(1) + +#define MTK_DP_4P1T 4 +#define MTK_DP_HDE 2 +#define MTK_DP_PIX_PER_ADDR 2 +#define MTK_DP_AUX_WAIT_REPLY_COUNT 20 +#define MTK_DP_TBC_BUF_READ_START_ADDR 0x8 +#define MTK_DP_TRAIN_VOLTAGE_LEVEL_RETRY 5 +#define MTK_DP_TRAIN_DOWNSCALE_RETRY 10 + +enum { + MTK_DP_CAL_GLB_BIAS_TRIM = 0, + MTK_DP_CAL_CLKTX_IMPSE, + MTK_DP_CAL_LN_TX_IMPSEL_PMOS_0, + MTK_DP_CAL_LN_TX_IMPSEL_PMOS_1, + MTK_DP_CAL_LN_TX_IMPSEL_PMOS_2, + MTK_DP_CAL_LN_TX_IMPSEL_PMOS_3, + MTK_DP_CAL_LN_TX_IMPSEL_NMOS_0, + MTK_DP_CAL_LN_TX_IMPSEL_NMOS_1, + MTK_DP_CAL_LN_TX_IMPSEL_NMOS_2, + MTK_DP_CAL_LN_TX_IMPSEL_NMOS_3, + MTK_DP_CAL_MAX, +}; + +struct mtk_dp_train_info { + bool sink_ssc; + bool cable_plugged_in; + /* link_rate is in multiple of 0.27Gbps */ + int link_rate; + int lane_count; + unsigned int channel_eq_pattern; +}; + +struct mtk_dp_info { + enum dp_pixelformat format; + struct videomode vm; +}; + +struct mtk_dp_efuse_fmt { + unsigned short idx; + unsigned short shift; + unsigned short mask; + unsigned short min_val; + unsigned short max_val; + unsigned short default_val; +}; + +struct mtk_dp { + bool enabled; + u8 max_lanes; + u8 max_linkrate; + u8 rx_cap[DP_RECEIVER_CAP_SIZE]; + u32 cal_data[MTK_DP_CAL_MAX]; + u32 irq_thread_handle; + /* irq_thread_lock is used to protect irq_thread_handle */ + spinlock_t irq_thread_lock; + + struct device *dev; + struct drm_bridge bridge; + struct drm_bridge *next_bridge; + struct drm_connector *conn; + struct drm_device *drm_dev; + struct drm_dp_aux aux; + + struct mtk_dp_info info; + struct mtk_dp_train_info train_info; + + struct platform_device *phy_dev; + struct phy *phy; + struct regmap *regs; +}; + +static const struct mtk_dp_efuse_fmt mtk_dp_efuse_data[MTK_DP_CAL_MAX] = { + [MTK_DP_CAL_GLB_BIAS_TRIM] = { + .idx = 3, + .shift = 27, + .mask = 0x1f, + .min_val = 1, + .max_val = 0x1e, + .default_val = 0xf, + }, + [MTK_DP_CAL_CLKTX_IMPSE] = { + .idx = 0, + .shift = 9, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_0] = { + .idx = 2, + .shift = 28, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_1] = { + .idx = 2, + .shift = 20, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_2] = { + .idx = 2, + .shift = 12, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_3] = { + .idx = 2, + .shift = 4, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_0] = { + .idx = 2, + .shift = 24, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_1] = { + .idx = 2, + .shift = 16, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_2] = { + .idx = 2, + .shift = 8, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_3] = { + .idx = 2, + .shift = 0, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, +}; + +static struct regmap_config mtk_dp_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = SEC_OFFSET + 0x90, + .name = "mtk-dp-registers", +}; + +static struct mtk_dp *mtk_dp_from_bridge(struct drm_bridge *b) +{ + return container_of(b, struct mtk_dp, bridge); +} + +static u32 mtk_dp_read(struct mtk_dp *mtk_dp, u32 offset) +{ + u32 read_val; + int ret; + + ret = regmap_read(mtk_dp->regs, offset, &read_val); + if (ret) { + dev_err(mtk_dp->dev, "Failed to read register 0x%x: %d\n", + offset, ret); + return 0; + } + + return read_val; +} + +static int mtk_dp_write(struct mtk_dp *mtk_dp, u32 offset, u32 val) +{ + int ret = regmap_write(mtk_dp->regs, offset, val); + + if (ret) + dev_err(mtk_dp->dev, + "Failed to write register 0x%x with value 0x%x\n", + offset, val); + return ret; +} + +static int mtk_dp_update_bits(struct mtk_dp *mtk_dp, u32 offset, + u32 val, u32 mask) +{ + int ret = regmap_update_bits(mtk_dp->regs, offset, mask, val); + + if (ret) + dev_err(mtk_dp->dev, + "Failed to update register 0x%x with value 0x%x, mask 0x%x\n", + offset, val, mask); + return ret; +} + +static void mtk_dp_bulk_16bit_write(struct mtk_dp *mtk_dp, u32 offset, u8 *buf, + size_t length) +{ + int i; + + /* 2 bytes per register */ + for (i = 0; i < length; i += 2) { + u32 val = buf[i] | (i + 1 < length ? buf[i + 1] << 8 : 0); + + if (mtk_dp_write(mtk_dp, offset + i * 2, val)) + return; + } +} + +static void mtk_dp_msa_bypass_enable(struct mtk_dp *mtk_dp, bool enable) +{ + u32 mask = HTOTAL_SEL_DP_ENC0_P0 | VTOTAL_SEL_DP_ENC0_P0 | + HSTART_SEL_DP_ENC0_P0 | VSTART_SEL_DP_ENC0_P0 | + HWIDTH_SEL_DP_ENC0_P0 | VHEIGHT_SEL_DP_ENC0_P0 | + HSP_SEL_DP_ENC0_P0 | HSW_SEL_DP_ENC0_P0 | + VSP_SEL_DP_ENC0_P0 | VSW_SEL_DP_ENC0_P0; + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3030, enable ? 0 : mask, mask); +} + +static void mtk_dp_set_msa(struct mtk_dp *mtk_dp) +{ + struct drm_display_mode mode; + struct videomode *vm = &mtk_dp->info.vm; + + drm_display_mode_from_videomode(vm, &mode); + + /* horizontal */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3010, + mode.htotal, HTOTAL_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3018, + vm->hsync_len + vm->hback_porch, + HSTART_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3028, + vm->hsync_len, HSW_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3028, + 0, HSP_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3020, + vm->hactive, HWIDTH_SW_DP_ENC0_P0_MASK); + + /* vertical */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3014, + mode.vtotal, VTOTAL_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_301C, + vm->vsync_len + vm->vback_porch, + VSTART_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_302C, + vm->vsync_len, VSW_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_302C, + 0, VSP_SW_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3024, + vm->vactive, VHEIGHT_SW_DP_ENC0_P0_MASK); + + /* horizontal */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3064, + vm->hactive, HDE_NUM_LAST_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3154, + mode.htotal, PGEN_HTOTAL_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3158, + vm->hfront_porch, + PGEN_HSYNC_RISING_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_315C, + vm->hsync_len, + PGEN_HSYNC_PULSE_WIDTH_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3160, + vm->hback_porch + vm->hsync_len, + PGEN_HFDE_START_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3164, + vm->hactive, + PGEN_HFDE_ACTIVE_WIDTH_DP_ENC0_P0_MASK); + + /* vertical */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3168, + mode.vtotal, + PGEN_VTOTAL_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_316C, + vm->vfront_porch, + PGEN_VSYNC_RISING_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3170, + vm->vsync_len, + PGEN_VSYNC_PULSE_WIDTH_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3174, + vm->vback_porch + vm->vsync_len, + PGEN_VFDE_START_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3178, + vm->vactive, + PGEN_VFDE_ACTIVE_WIDTH_DP_ENC0_P0_MASK); +} + +static int mtk_dp_set_color_format(struct mtk_dp *mtk_dp, + enum dp_pixelformat color_format) +{ + u32 val; + + /* update MISC0 */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3034, + color_format << DP_TEST_COLOR_FORMAT_SHIFT, + DP_TEST_COLOR_FORMAT_MASK); + + switch (color_format) { + case DP_PIXELFORMAT_YUV422: + val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_YCBCR422; + break; + case DP_PIXELFORMAT_RGB: + val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_RGB; + break; + default: + drm_warn(mtk_dp->drm_dev, "Unsupported color format: %d\n", + color_format); + return -EINVAL; + } + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_303C, + val, PIXEL_ENCODE_FORMAT_DP_ENC0_P0_MASK); + return 0; +} + +static void mtk_dp_set_color_depth(struct mtk_dp *mtk_dp) +{ + /* Only support 8 bits currently */ + /* Update MISC0 */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3034, + DP_MSA_MISC_8_BPC, DP_TEST_BIT_DEPTH_MASK); + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_303C, + VIDEO_COLOR_DEPTH_DP_ENC0_P0_8BIT, + VIDEO_COLOR_DEPTH_DP_ENC0_P0_MASK); +} + +static void mtk_dp_config_mn_mode(struct mtk_dp *mtk_dp) +{ + /* 0: hw mode, 1: sw mode */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3004, + 0, VIDEO_M_CODE_SEL_DP_ENC0_P0_MASK); +} + +static void mtk_dp_set_sram_read_start(struct mtk_dp *mtk_dp, u32 val) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_303C, + val, SRAM_START_READ_THRD_DP_ENC0_P0_MASK); +} + +static void mtk_dp_setup_encoder(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_303C, + VIDEO_MN_GEN_EN_DP_ENC0_P0, + VIDEO_MN_GEN_EN_DP_ENC0_P0); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3040, + SDP_DOWN_CNT_DP_ENC0_P0_VAL, + SDP_DOWN_CNT_INIT_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3364, + SDP_DOWN_CNT_IN_HBLANK_DP_ENC1_P0_VAL, + SDP_DOWN_CNT_INIT_IN_HBLANK_DP_ENC1_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3300, + VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_VAL << 8, + VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3364, + FIFO_READ_START_POINT_DP_ENC1_P0_VAL << 12, + FIFO_READ_START_POINT_DP_ENC1_P0_MASK); + mtk_dp_write(mtk_dp, MTK_DP_ENC1_P0_3368, DP_ENC1_P0_3368_VAL); +} + +static void mtk_dp_pg_enable(struct mtk_dp *mtk_dp, bool enable) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3038, + enable ? VIDEO_SOURCE_SEL_DP_ENC0_P0_MASK : 0, + VIDEO_SOURCE_SEL_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_31B0, + PGEN_PATTERN_SEL_VAL << 4, PGEN_PATTERN_SEL_MASK); +} + +static void mtk_dp_aux_irq_clear(struct mtk_dp *mtk_dp) +{ + mtk_dp_write(mtk_dp, MTK_DP_AUX_P0_3640, DP_AUX_P0_3640_VAL); +} + +static void mtk_dp_aux_set_cmd(struct mtk_dp *mtk_dp, u8 cmd, u32 addr) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3644, + cmd, MCU_REQUEST_COMMAND_AUX_TX_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3648, + addr, MCU_REQUEST_ADDRESS_LSB_AUX_TX_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_364C, + addr >> 16, MCU_REQUEST_ADDRESS_MSB_AUX_TX_P0_MASK); +} + +static void mtk_dp_aux_clear_fifo(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3650, + MCU_ACK_TRAN_COMPLETE_AUX_TX_P0, + MCU_ACK_TRAN_COMPLETE_AUX_TX_P0 | + PHY_FIFO_RST_AUX_TX_P0_MASK | + MCU_REQ_DATA_NUM_AUX_TX_P0_MASK); +} + +static void mtk_dp_aux_request_ready(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3630, + AUX_TX_REQUEST_READY_AUX_TX_P0, + AUX_TX_REQUEST_READY_AUX_TX_P0); +} + +static void mtk_dp_aux_fill_write_fifo(struct mtk_dp *mtk_dp, u8 *buf, + size_t length) +{ + mtk_dp_bulk_16bit_write(mtk_dp, MTK_DP_AUX_P0_3708, buf, length); +} + +static void mtk_dp_aux_read_rx_fifo(struct mtk_dp *mtk_dp, u8 *buf, + size_t length, int read_delay) +{ + int read_pos; + + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3620, + 0, AUX_RD_MODE_AUX_TX_P0_MASK); + + for (read_pos = 0; read_pos < length; read_pos++) { + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3620, + AUX_RX_FIFO_READ_PULSE_TX_P0, + AUX_RX_FIFO_READ_PULSE_TX_P0); + + /* Hardware needs time to update the data */ + usleep_range(read_delay, read_delay * 2); + buf[read_pos] = (u8)(mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3620) & + AUX_RX_FIFO_READ_DATA_AUX_TX_P0_MASK); + } +} + +static void mtk_dp_aux_set_length(struct mtk_dp *mtk_dp, size_t length) +{ + if (length > 0) { + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3650, + (length - 1) << 12, + MCU_REQ_DATA_NUM_AUX_TX_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_362C, + 0, + AUX_NO_LENGTH_AUX_TX_P0 | + AUX_TX_AUXTX_OV_EN_AUX_TX_P0_MASK | + AUX_RESERVED_RW_0_AUX_TX_P0_MASK); + } else { + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_362C, + AUX_NO_LENGTH_AUX_TX_P0, + AUX_NO_LENGTH_AUX_TX_P0 | + AUX_TX_AUXTX_OV_EN_AUX_TX_P0_MASK | + AUX_RESERVED_RW_0_AUX_TX_P0_MASK); + } +} + +static int mtk_dp_aux_wait_for_completion(struct mtk_dp *mtk_dp, bool is_read) +{ + int wait_reply = MTK_DP_AUX_WAIT_REPLY_COUNT; + + while (--wait_reply) { + u32 aux_irq_status; + + if (is_read) { + u32 fifo_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3618); + + if (fifo_status & + (AUX_RX_FIFO_WRITE_POINTER_AUX_TX_P0_MASK | + AUX_RX_FIFO_FULL_AUX_TX_P0_MASK)) { + return 0; + } + } + + aux_irq_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3640); + if (aux_irq_status & AUX_RX_AUX_RECV_COMPLETE_IRQ_AUX_TX_P0) + return 0; + + if (aux_irq_status & AUX_400US_TIMEOUT_IRQ_AUX_TX_P0) + return -ETIMEDOUT; + + /* Give the hardware a chance to reach completion before retrying */ + usleep_range(100, 500); + } + + return -ETIMEDOUT; +} + +static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd, + u32 addr, u8 *buf, size_t length) +{ + int ret; + u32 reply_cmd; + + if (is_read && (length > DP_AUX_MAX_PAYLOAD_BYTES || + (cmd == DP_AUX_NATIVE_READ && !length))) + return -EINVAL; + + if (!is_read) + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3704, + AUX_TX_FIFO_NEW_MODE_EN_AUX_TX_P0, + AUX_TX_FIFO_NEW_MODE_EN_AUX_TX_P0); + + /* We need to clear fifo and irq before sending commands to the sink device. */ + mtk_dp_aux_clear_fifo(mtk_dp); + mtk_dp_aux_irq_clear(mtk_dp); + + mtk_dp_aux_set_cmd(mtk_dp, cmd, addr); + mtk_dp_aux_set_length(mtk_dp, length); + + if (!is_read) { + if (length) + mtk_dp_aux_fill_write_fifo(mtk_dp, buf, length); + + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3704, + AUX_TX_FIFO_WDATA_NEW_MODE_T_AUX_TX_P0_MASK, + AUX_TX_FIFO_WDATA_NEW_MODE_T_AUX_TX_P0_MASK); + } + + mtk_dp_aux_request_ready(mtk_dp); + + /* Wait for feedback from sink device. */ + ret = mtk_dp_aux_wait_for_completion(mtk_dp, is_read); + + reply_cmd = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3624) & + AUX_RX_REPLY_COMMAND_AUX_TX_P0_MASK; + + if (ret || reply_cmd) { + u32 phy_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3628) & + AUX_RX_PHY_STATE_AUX_TX_P0_MASK; + if (phy_status != AUX_RX_PHY_STATE_AUX_TX_P0_RX_IDLE) { + drm_err(mtk_dp->drm_dev, + "AUX Rx Aux hang, need SW reset\n"); + return -EIO; + } + + return -ETIMEDOUT; + } + + if (!length) { + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_362C, + 0, + AUX_NO_LENGTH_AUX_TX_P0 | + AUX_TX_AUXTX_OV_EN_AUX_TX_P0_MASK | + AUX_RESERVED_RW_0_AUX_TX_P0_MASK); + } else if (is_read) { + int read_delay; + + if (cmd == (DP_AUX_I2C_READ | DP_AUX_I2C_MOT) || + cmd == DP_AUX_I2C_READ) + read_delay = 500; + else + read_delay = 100; + + mtk_dp_aux_read_rx_fifo(mtk_dp, buf, length, read_delay); + } + + return 0; +} + +static void mtk_dp_set_swing_pre_emphasis(struct mtk_dp *mtk_dp, int lane_num, + int swing_val, int preemphasis) +{ + u32 lane_shift = lane_num * DP_TX1_VOLT_SWING_SHIFT; + + dev_dbg(mtk_dp->dev, + "link training: swing_val = 0x%x, pre-emphasis = 0x%x\n", + swing_val, preemphasis); + + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_SWING_EMP, + swing_val << (DP_TX0_VOLT_SWING_SHIFT + lane_shift), + DP_TX0_VOLT_SWING_MASK << lane_shift); + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_SWING_EMP, + preemphasis << (DP_TX0_PRE_EMPH_SHIFT + lane_shift), + DP_TX0_PRE_EMPH_MASK << lane_shift); +} + +static void mtk_dp_reset_swing_pre_emphasis(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_SWING_EMP, + 0, + DP_TX0_VOLT_SWING_MASK | + DP_TX1_VOLT_SWING_MASK | + DP_TX2_VOLT_SWING_MASK | + DP_TX3_VOLT_SWING_MASK | + DP_TX0_PRE_EMPH_MASK | + DP_TX1_PRE_EMPH_MASK | + DP_TX2_PRE_EMPH_MASK | + DP_TX3_PRE_EMPH_MASK); +} + +static u32 mtk_dp_swirq_get_clear(struct mtk_dp *mtk_dp) +{ + u32 irq_status = mtk_dp_read(mtk_dp, MTK_DP_TRANS_P0_35D0) & + SW_IRQ_FINAL_STATUS_DP_TRANS_P0_MASK; + + if (irq_status) { + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_35C8, + irq_status, SW_IRQ_CLR_DP_TRANS_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_35C8, + 0, SW_IRQ_CLR_DP_TRANS_P0_MASK); + } + + return irq_status; +} + +static u32 mtk_dp_hwirq_get_clear(struct mtk_dp *mtk_dp) +{ + u32 irq_status = (mtk_dp_read(mtk_dp, MTK_DP_TRANS_P0_3418) & + IRQ_STATUS_DP_TRANS_P0_MASK) >> 12; + + if (irq_status) { + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3418, + irq_status, IRQ_CLR_DP_TRANS_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3418, + 0, IRQ_CLR_DP_TRANS_P0_MASK); + } + + return irq_status; +} + +static void mtk_dp_hwirq_enable(struct mtk_dp *mtk_dp, bool enable) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3418, + enable ? 0 : + IRQ_MASK_DP_TRANS_P0_DISC_IRQ | + IRQ_MASK_DP_TRANS_P0_CONN_IRQ | + IRQ_MASK_DP_TRANS_P0_INT_IRQ, + IRQ_MASK_DP_TRANS_P0_MASK); +} + +static void mtk_dp_initialize_settings(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_342C, + XTAL_FREQ_DP_TRANS_P0_DEFAULT, + XTAL_FREQ_DP_TRANS_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3540, + FEC_CLOCK_EN_MODE_DP_TRANS_P0, + FEC_CLOCK_EN_MODE_DP_TRANS_P0); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_31EC, + AUDIO_CH_SRC_SEL_DP_ENC0_P0, + AUDIO_CH_SRC_SEL_DP_ENC0_P0); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_304C, + 0, SDP_VSYNC_RISING_MASK_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_IRQ_MASK, + IRQ_MASK_AUX_TOP_IRQ, IRQ_MASK_AUX_TOP_IRQ); +} + +static void mtk_dp_initialize_hpd_detect_settings(struct mtk_dp *mtk_dp) +{ + u32 val; + /* Debounce threshold */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, + 8, HPD_DEB_THD_DP_TRANS_P0_MASK); + + val = (HPD_INT_THD_DP_TRANS_P0_LOWER_500US | + HPD_INT_THD_DP_TRANS_P0_UPPER_1100US) << 4; + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, + val, HPD_INT_THD_DP_TRANS_P0_MASK); + + /* + * Connect threshold 1.5ms + 5 x 0.1ms = 2ms + * Disconnect threshold 1.5ms + 5 x 0.1ms = 2ms + */ + val = (5 << 8) | (5 << 12); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, + val, + HPD_DISC_THD_DP_TRANS_P0_MASK | + HPD_CONN_THD_DP_TRANS_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3430, + HPD_INT_THD_ECO_DP_TRANS_P0_HIGH_BOUND_EXT, + HPD_INT_THD_ECO_DP_TRANS_P0_MASK); +} + +static void mtk_dp_initialize_aux_settings(struct mtk_dp *mtk_dp) +{ + /* modify timeout threshold = 0x1595 */ + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_360C, + AUX_TIMEOUT_THR_AUX_TX_P0_VAL, + AUX_TIMEOUT_THR_AUX_TX_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3658, + 0, AUX_TX_OV_EN_AUX_TX_P0_MASK); + /* 25 for 26M */ + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3634, + AUX_TX_OVER_SAMPLE_RATE_FOR_26M << 8, + AUX_TX_OVER_SAMPLE_RATE_AUX_TX_P0_MASK); + /* 13 for 26M */ + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3614, + AUX_RX_UI_CNT_THR_AUX_FOR_26M, + AUX_RX_UI_CNT_THR_AUX_TX_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_37C8, + MTK_ATOP_EN_AUX_TX_P0, + MTK_ATOP_EN_AUX_TX_P0); +} + +static void mtk_dp_initialize_digital_settings(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_304C, + 0, VBID_VIDEO_MUTE_DP_ENC0_P0_MASK); + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3368, + BS2BS_MODE_DP_ENC1_P0_VAL << 12, + BS2BS_MODE_DP_ENC1_P0_MASK); + + /* dp tx encoder reset all sw */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3004, + DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0, + DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0); + + /* Wait for sw reset to complete */ + usleep_range(1000, 5000); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3004, + 0, DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0); +} + +static void mtk_dp_digital_sw_reset(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_340C, + DP_TX_TRANSMITTER_4P_RESET_SW_DP_TRANS_P0, + DP_TX_TRANSMITTER_4P_RESET_SW_DP_TRANS_P0); + + /* Wait for sw reset to complete */ + usleep_range(1000, 5000); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_340C, + 0, DP_TX_TRANSMITTER_4P_RESET_SW_DP_TRANS_P0); +} + +static void mtk_dp_set_lanes(struct mtk_dp *mtk_dp, int lanes) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_35F0, + lanes == 0 ? 0 : DP_TRANS_DUMMY_RW_0, + DP_TRANS_DUMMY_RW_0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3000, + lanes, LANE_NUM_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_34A4, + lanes << 2, LANE_NUM_DP_TRANS_P0_MASK); +} + +static void mtk_dp_get_calibration_data(struct mtk_dp *mtk_dp) +{ + const struct mtk_dp_efuse_fmt *fmt; + struct device *dev = mtk_dp->dev; + struct nvmem_cell *cell; + u32 *cal_data = mtk_dp->cal_data; + u32 *buf; + int i; + size_t len; + + cell = nvmem_cell_get(dev, "dp_calibration_data"); + if (IS_ERR(cell)) { + dev_warn(dev, "Failed to get nvmem cell dp_calibration_data\n"); + goto use_default_val; + } + + buf = (u32 *)nvmem_cell_read(cell, &len); + nvmem_cell_put(cell); + + if (IS_ERR(buf) || ((len / sizeof(u32)) != 4)) { + dev_warn(dev, "Failed to read nvmem_cell_read\n"); + + if (!IS_ERR(buf)) + kfree(buf); + + goto use_default_val; + } + + for (i = 0; i < MTK_DP_CAL_MAX; i++) { + fmt = &mtk_dp_efuse_data[i]; + cal_data[i] = (buf[fmt->idx] >> fmt->shift) & fmt->mask; + + if (cal_data[i] < fmt->min_val || cal_data[i] > fmt->max_val) { + dev_warn(mtk_dp->dev, "Invalid efuse data, idx = %d\n", i); + kfree(buf); + goto use_default_val; + } + } + kfree(buf); + + return; + +use_default_val: + dev_warn(mtk_dp->dev, "Use default calibration data\n"); + for (i = 0; i < MTK_DP_CAL_MAX; i++) + cal_data[i] = mtk_dp_efuse_data[i].default_val; +} + +static void mtk_dp_set_calibration_data(struct mtk_dp *mtk_dp) +{ + u32 *cal_data = mtk_dp->cal_data; + + mtk_dp_update_bits(mtk_dp, DP_PHY_GLB_DPAUX_TX, + cal_data[MTK_DP_CAL_CLKTX_IMPSE] << 20, + RG_CKM_PT0_CKTX_IMPSEL); + mtk_dp_update_bits(mtk_dp, DP_PHY_GLB_BIAS_GEN_00, + cal_data[MTK_DP_CAL_GLB_BIAS_TRIM] << 16, + RG_XTP_GLB_BIAS_INTR_CTRL); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_0, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_0] << 12, + RG_XTP_LN0_TX_IMPSEL_PMOS); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_0, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_0] << 16, + RG_XTP_LN0_TX_IMPSEL_NMOS); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_1, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_1] << 12, + RG_XTP_LN1_TX_IMPSEL_PMOS); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_1, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_1] << 16, + RG_XTP_LN1_TX_IMPSEL_NMOS); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_2, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_2] << 12, + RG_XTP_LN2_TX_IMPSEL_PMOS); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_2, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_2] << 16, + RG_XTP_LN2_TX_IMPSEL_NMOS); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_3, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_3] << 12, + RG_XTP_LN3_TX_IMPSEL_PMOS); + mtk_dp_update_bits(mtk_dp, DP_PHY_LANE_TX_3, + cal_data[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_3] << 16, + RG_XTP_LN3_TX_IMPSEL_NMOS); +} + +static int mtk_dp_phy_configure(struct mtk_dp *mtk_dp, + u32 link_rate, int lane_count) +{ + int ret; + union phy_configure_opts phy_opts = { + .dp = { + .link_rate = drm_dp_bw_code_to_link_rate(link_rate) / 100, + .set_rate = 1, + .lanes = lane_count, + .set_lanes = 1, + .ssc = mtk_dp->train_info.sink_ssc, + } + }; + + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, DP_PWR_STATE_BANDGAP, + DP_PWR_STATE_MASK); + + ret = phy_configure(mtk_dp->phy, &phy_opts); + if (ret) + return ret; + + mtk_dp_set_calibration_data(mtk_dp); + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL_LANE, DP_PWR_STATE_MASK); + + return 0; +} + +static void mtk_dp_set_idle_pattern(struct mtk_dp *mtk_dp, bool enable) +{ + u32 val = POST_MISC_DATA_LANE0_OV_DP_TRANS_P0_MASK | + POST_MISC_DATA_LANE1_OV_DP_TRANS_P0_MASK | + POST_MISC_DATA_LANE2_OV_DP_TRANS_P0_MASK | + POST_MISC_DATA_LANE3_OV_DP_TRANS_P0_MASK; + + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3580, + enable ? val : 0, val); +} + +static void mtk_dp_train_set_pattern(struct mtk_dp *mtk_dp, int pattern) +{ + /* TPS1 */ + if (pattern == 1) + mtk_dp_set_idle_pattern(mtk_dp, false); + + mtk_dp_update_bits(mtk_dp, + MTK_DP_TRANS_P0_3400, + pattern ? BIT(pattern - 1) << 12 : 0, + PATTERN1_EN_DP_TRANS_P0_MASK | + PATTERN2_EN_DP_TRANS_P0_MASK | + PATTERN3_EN_DP_TRANS_P0_MASK | + PATTERN4_EN_DP_TRANS_P0_MASK); +} + +static void mtk_dp_set_enhanced_frame_mode(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3000, + ENHANCED_FRAME_EN_DP_ENC0_P0, + ENHANCED_FRAME_EN_DP_ENC0_P0); +} + +static void mtk_dp_training_set_scramble(struct mtk_dp *mtk_dp, bool enable) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3404, + enable ? DP_SCR_EN_DP_TRANS_P0_MASK : 0, + DP_SCR_EN_DP_TRANS_P0_MASK); +} + +static void mtk_dp_video_mute(struct mtk_dp *mtk_dp, bool enable) +{ + struct arm_smccc_res res; + u32 val = VIDEO_MUTE_SEL_DP_ENC0_P0 | + (enable ? VIDEO_MUTE_SW_DP_ENC0_P0 : 0); + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3000, + val, + VIDEO_MUTE_SEL_DP_ENC0_P0 | + VIDEO_MUTE_SW_DP_ENC0_P0); + + arm_smccc_smc(MTK_DP_SIP_CONTROL_AARCH32, + MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, enable, + 0, 0, 0, 0, 0, &res); + + dev_dbg(mtk_dp->dev, "smc cmd: 0x%x, p1: 0x%x, ret: 0x%lx-0x%lx\n", + MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, enable, res.a0, res.a1); +} + +static void mtk_dp_power_enable(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_RESET_AND_PROBE, + 0, SW_RST_B_PHYD); + + /* Wait for power enable */ + usleep_range(10, 200); + + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_RESET_AND_PROBE, + SW_RST_B_PHYD, SW_RST_B_PHYD); + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, DP_PWR_STATE_MASK); + mtk_dp_write(mtk_dp, MTK_DP_1040, + RG_DPAUX_RX_VALID_DEGLITCH_EN | RG_XTP_GLB_CKDET_EN | + RG_DPAUX_RX_EN); + mtk_dp_update_bits(mtk_dp, MTK_DP_0034, 0, DA_CKM_CKTX0_EN_FORCE_EN); +} + +static void mtk_dp_power_disable(struct mtk_dp *mtk_dp) +{ + mtk_dp_write(mtk_dp, MTK_DP_TOP_PWR_STATE, 0); + + mtk_dp_update_bits(mtk_dp, MTK_DP_0034, + DA_CKM_CKTX0_EN_FORCE_EN, DA_CKM_CKTX0_EN_FORCE_EN); + + /* Disable RX */ + mtk_dp_write(mtk_dp, MTK_DP_1040, 0); + mtk_dp_write(mtk_dp, MTK_DP_TOP_MEM_PD, + 0x550 | FUSE_SEL | MEM_ISO_EN); +} + +static void mtk_dp_initialize_priv_data(struct mtk_dp *mtk_dp) +{ + mtk_dp->train_info.link_rate = DP_LINK_BW_5_4; + mtk_dp->train_info.lane_count = mtk_dp->max_lanes; + mtk_dp->train_info.cable_plugged_in = false; + + mtk_dp->info.format = DP_PIXELFORMAT_RGB; + memset(&mtk_dp->info.vm, 0, sizeof(struct videomode)); +} + +static void mtk_dp_setup_tu(struct mtk_dp *mtk_dp) +{ + u32 sram_read_start = min_t(u32, MTK_DP_TBC_BUF_READ_START_ADDR, + mtk_dp->info.vm.hactive / + mtk_dp->train_info.lane_count / + MTK_DP_4P1T / MTK_DP_HDE / + MTK_DP_PIX_PER_ADDR); + mtk_dp_set_sram_read_start(mtk_dp, sram_read_start); + mtk_dp_setup_encoder(mtk_dp); +} + +static void mtk_dp_set_tx_out(struct mtk_dp *mtk_dp) +{ + mtk_dp_setup_tu(mtk_dp); +} + +static void mtk_dp_train_update_swing_pre(struct mtk_dp *mtk_dp, int lanes, + u8 dpcd_adjust_req[2]) +{ + int lane; + + for (lane = 0; lane < lanes; ++lane) { + u8 val; + u8 swing; + u8 preemphasis; + int index = lane / 2; + int shift = lane % 2 ? DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : 0; + + swing = (dpcd_adjust_req[index] >> shift) & + DP_ADJUST_VOLTAGE_SWING_LANE0_MASK; + preemphasis = ((dpcd_adjust_req[index] >> shift) & + DP_ADJUST_PRE_EMPHASIS_LANE0_MASK) >> + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT; + val = swing << DP_TRAIN_VOLTAGE_SWING_SHIFT | + preemphasis << DP_TRAIN_PRE_EMPHASIS_SHIFT; + + if (swing == DP_TRAIN_VOLTAGE_SWING_LEVEL_3) + val |= DP_TRAIN_MAX_SWING_REACHED; + if (preemphasis == 3) + val |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + mtk_dp_set_swing_pre_emphasis(mtk_dp, lane, swing, preemphasis); + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_TRAINING_LANE0_SET + lane, + val); + } +} + +static void mtk_dp_pattern(struct mtk_dp *mtk_dp, bool is_tps1) +{ + int pattern; + unsigned int aux_offset; + + if (is_tps1) { + pattern = 1; + aux_offset = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1; + } else { + aux_offset = mtk_dp->train_info.channel_eq_pattern; + + switch (mtk_dp->train_info.channel_eq_pattern) { + case DP_TRAINING_PATTERN_4: + pattern = 4; + break; + case DP_TRAINING_PATTERN_3: + pattern = 3; + aux_offset |= DP_LINK_SCRAMBLING_DISABLE; + break; + case DP_TRAINING_PATTERN_2: + default: + pattern = 2; + aux_offset |= DP_LINK_SCRAMBLING_DISABLE; + break; + } + } + + mtk_dp_train_set_pattern(mtk_dp, pattern); + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_TRAINING_PATTERN_SET, aux_offset); +} + +static int mtk_dp_train_setting(struct mtk_dp *mtk_dp, u8 target_link_rate, + u8 target_lane_count) +{ + int ret; + + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_LINK_BW_SET, target_link_rate); + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_LANE_COUNT_SET, + target_lane_count | DP_LANE_COUNT_ENHANCED_FRAME_EN); + + if (mtk_dp->train_info.sink_ssc) + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_DOWNSPREAD_CTRL, + DP_SPREAD_AMP_0_5); + + mtk_dp_set_lanes(mtk_dp, target_lane_count / 2); + ret = mtk_dp_phy_configure(mtk_dp, target_link_rate, target_lane_count); + if (ret) + return ret; + + dev_dbg(mtk_dp->dev, + "Link train target_link_rate = 0x%x, target_lane_count = 0x%x\n", + target_link_rate, target_lane_count); + + return 0; +} + +static int mtk_dp_train_cr(struct mtk_dp *mtk_dp, u8 target_lane_count) +{ + u8 lane_adjust[2] = {}; + u8 link_status[DP_LINK_STATUS_SIZE] = {}; + u8 prev_lane_adjust = 0xff; + int train_retries = 0; + int voltage_retries = 0; + + mtk_dp_pattern(mtk_dp, true); + + /* In DP spec 1.4, the retry count of CR is defined as 10. */ + do { + train_retries++; + if (!mtk_dp->train_info.cable_plugged_in) { + mtk_dp_train_set_pattern(mtk_dp, 0); + return -ENODEV; + } + + drm_dp_dpcd_read(&mtk_dp->aux, DP_ADJUST_REQUEST_LANE0_1, + lane_adjust, sizeof(lane_adjust)); + mtk_dp_train_update_swing_pre(mtk_dp, target_lane_count, + lane_adjust); + + drm_dp_link_train_clock_recovery_delay(&mtk_dp->aux, + mtk_dp->rx_cap); + + /* check link status from sink device */ + drm_dp_dpcd_read_link_status(&mtk_dp->aux, link_status); + if (drm_dp_clock_recovery_ok(link_status, + target_lane_count)) { + dev_dbg(mtk_dp->dev, "Link train CR pass\n"); + return 0; + } + + /* + * In DP spec 1.4, if current voltage level is the same + * with previous voltage level, we need to retry 5 times. + */ + if (prev_lane_adjust == link_status[4]) { + voltage_retries++; + /* + * Condition of CR fail: + * 1. Failed to pass CR using the same voltage + * level over five times. + * 2. Failed to pass CR when the current voltage + * level is the same with previous voltage + * level and reach max voltage level (3). + */ + if (voltage_retries > MTK_DP_TRAIN_VOLTAGE_LEVEL_RETRY || + (prev_lane_adjust & DP_ADJUST_VOLTAGE_SWING_LANE0_MASK) == 3) { + dev_dbg(mtk_dp->dev, "Link train CR fail\n"); + break; + } + } else { + /* + * If the voltage level is changed, we need to + * re-calculate this retry count. + */ + voltage_retries = 0; + } + prev_lane_adjust = link_status[4]; + } while (train_retries < MTK_DP_TRAIN_DOWNSCALE_RETRY); + + /* Failed to train CR, and disable pattern. */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + mtk_dp_train_set_pattern(mtk_dp, 0); + + return -ETIMEDOUT; +} + +static int mtk_dp_train_eq(struct mtk_dp *mtk_dp, u8 target_lane_count) +{ + u8 lane_adjust[2] = {}; + u8 link_status[DP_LINK_STATUS_SIZE] = {}; + int train_retries = 0; + + mtk_dp_pattern(mtk_dp, false); + + do { + train_retries++; + if (!mtk_dp->train_info.cable_plugged_in) { + mtk_dp_train_set_pattern(mtk_dp, 0); + return -ENODEV; + } + + drm_dp_dpcd_read(&mtk_dp->aux, DP_ADJUST_REQUEST_LANE0_1, + lane_adjust, sizeof(lane_adjust)); + mtk_dp_train_update_swing_pre(mtk_dp, target_lane_count, + lane_adjust); + + drm_dp_link_train_channel_eq_delay(&mtk_dp->aux, + mtk_dp->rx_cap); + + /* check link status from sink device */ + drm_dp_dpcd_read_link_status(&mtk_dp->aux, link_status); + if (drm_dp_channel_eq_ok(link_status, target_lane_count)) { + dev_dbg(mtk_dp->dev, "Link train EQ pass\n"); + + /* Training done, and disable pattern. */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + mtk_dp_train_set_pattern(mtk_dp, 0); + return 0; + } + dev_dbg(mtk_dp->dev, "Link train EQ fail\n"); + } while (train_retries < MTK_DP_TRAIN_DOWNSCALE_RETRY); + + /* Failed to train EQ, and disable pattern. */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + mtk_dp_train_set_pattern(mtk_dp, 0); + + return -ETIMEDOUT; +} + +static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp) +{ + u8 val; + ssize_t ret; + + drm_dp_read_dpcd_caps(&mtk_dp->aux, mtk_dp->rx_cap); + + if (drm_dp_tps4_supported(mtk_dp->rx_cap)) + mtk_dp->train_info.channel_eq_pattern = DP_TRAINING_PATTERN_4; + else if (drm_dp_tps3_supported(mtk_dp->rx_cap)) + mtk_dp->train_info.channel_eq_pattern = DP_TRAINING_PATTERN_3; + else + mtk_dp->train_info.channel_eq_pattern = DP_TRAINING_PATTERN_2; + + mtk_dp->train_info.sink_ssc = drm_dp_max_downspread(mtk_dp->rx_cap); + + ret = drm_dp_dpcd_readb(&mtk_dp->aux, DP_MSTM_CAP, &val); + if (ret < 1) { + drm_err(mtk_dp->drm_dev, "Read mstm cap failed\n"); + return ret == 0 ? -EIO : ret; + } + + if (val & DP_MST_CAP) { + /* Clear DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 */ + ret = drm_dp_dpcd_readb(&mtk_dp->aux, + DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0, + &val); + if (ret < 1) { + drm_err(mtk_dp->drm_dev, "Read irq vector failed\n"); + return ret == 0 ? -EIO : ret; + } + + if (val) + drm_dp_dpcd_writeb(&mtk_dp->aux, + DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0, + val); + } + + return 0; +} + +static void mtk_dp_train_change_mode(struct mtk_dp *mtk_dp) +{ + phy_reset(mtk_dp->phy); + mtk_dp_reset_swing_pre_emphasis(mtk_dp); +} + +static int mtk_dp_training(struct mtk_dp *mtk_dp) +{ + int ret; + u8 lane_count, link_rate, train_limit, max_link_rate; + + link_rate = min_t(u8, mtk_dp->max_linkrate, + mtk_dp->rx_cap[DP_MAX_LINK_RATE]); + max_link_rate = link_rate; + lane_count = min_t(u8, mtk_dp->max_lanes, + drm_dp_max_lane_count(mtk_dp->rx_cap)); + + /* + * TPS are generated by the hardware pattern generator. From the + * hardware setting we need to disable this scramble setting before + * use the TPS pattern generator. + */ + mtk_dp_training_set_scramble(mtk_dp, false); + + for (train_limit = 6; train_limit > 0; train_limit--) { + mtk_dp_train_change_mode(mtk_dp); + + ret = mtk_dp_train_setting(mtk_dp, link_rate, lane_count); + if (ret) + return ret; + + ret = mtk_dp_train_cr(mtk_dp, lane_count); + if (ret == -ENODEV) { + return ret; + } else if (ret) { + /* reduce link rate */ + switch (link_rate) { + case DP_LINK_BW_1_62: + lane_count = lane_count / 2; + link_rate = max_link_rate; + if (lane_count == 0) + return -EIO; + break; + case DP_LINK_BW_2_7: + link_rate = DP_LINK_BW_1_62; + break; + case DP_LINK_BW_5_4: + link_rate = DP_LINK_BW_2_7; + break; + case DP_LINK_BW_8_1: + link_rate = DP_LINK_BW_5_4; + break; + default: + return -EINVAL; + }; + continue; + } + + ret = mtk_dp_train_eq(mtk_dp, lane_count); + if (ret == -ENODEV) { + return ret; + } else if (ret) { + /* reduce lane count */ + if (lane_count == 0) + return -EIO; + lane_count /= 2; + continue; + } + + /* if we can run to this, training is done. */ + break; + } + + if (train_limit == 0) + return -ETIMEDOUT; + + mtk_dp->train_info.link_rate = link_rate; + mtk_dp->train_info.lane_count = lane_count; + + /* + * After training done, we need to output normal stream instead of TPS, + * so we need to enable scramble. + */ + mtk_dp_training_set_scramble(mtk_dp, true); + mtk_dp_set_enhanced_frame_mode(mtk_dp); + + return 0; +} + +static void mtk_dp_video_enable(struct mtk_dp *mtk_dp, bool enable) +{ + /* the mute sequence is different between enable and disable */ + if (enable) { + mtk_dp_msa_bypass_enable(mtk_dp, false); + mtk_dp_pg_enable(mtk_dp, false); + mtk_dp_set_tx_out(mtk_dp); + mtk_dp_video_mute(mtk_dp, false); + } else { + mtk_dp_video_mute(mtk_dp, true); + mtk_dp_pg_enable(mtk_dp, true); + mtk_dp_msa_bypass_enable(mtk_dp, true); + } +} + +static int mtk_dp_video_config(struct mtk_dp *mtk_dp) +{ + mtk_dp_config_mn_mode(mtk_dp); + mtk_dp_set_msa(mtk_dp); + mtk_dp_set_color_depth(mtk_dp); + return mtk_dp_set_color_format(mtk_dp, mtk_dp->info.format); +} + +static void mtk_dp_init_port(struct mtk_dp *mtk_dp) +{ + mtk_dp_set_idle_pattern(mtk_dp, true); + mtk_dp_initialize_priv_data(mtk_dp); + + mtk_dp_initialize_settings(mtk_dp); + mtk_dp_initialize_aux_settings(mtk_dp); + mtk_dp_initialize_digital_settings(mtk_dp); + + mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3690, + RX_REPLY_COMPLETE_MODE_AUX_TX_P0, + RX_REPLY_COMPLETE_MODE_AUX_TX_P0); + mtk_dp_initialize_hpd_detect_settings(mtk_dp); + + mtk_dp_digital_sw_reset(mtk_dp); +} + +static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev) +{ + struct mtk_dp *mtk_dp = dev; + unsigned long flags; + u32 status; + + spin_lock_irqsave(&mtk_dp->irq_thread_lock, flags); + status = mtk_dp->irq_thread_handle; + mtk_dp->irq_thread_handle = 0; + spin_unlock_irqrestore(&mtk_dp->irq_thread_lock, flags); + + if (status & MTK_DP_THREAD_CABLE_STATE_CHG) + drm_helper_hpd_irq_event(mtk_dp->bridge.dev); + + if (status & MTK_DP_THREAD_HPD_EVENT) + dev_dbg(mtk_dp->dev, "Receive IRQ from sink devices\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t mtk_dp_hpd_event(int hpd, void *dev) +{ + struct mtk_dp *mtk_dp = dev; + bool cable_sta_chg = false; + unsigned long flags; + u32 irq_status = mtk_dp_swirq_get_clear(mtk_dp) | + mtk_dp_hwirq_get_clear(mtk_dp); + + if (!irq_status) + return IRQ_HANDLED; + + spin_lock_irqsave(&mtk_dp->irq_thread_lock, flags); + + if (irq_status & MTK_DP_HPD_INTERRUPT) + mtk_dp->irq_thread_handle |= MTK_DP_THREAD_HPD_EVENT; + + /* Cable state is changed. */ + if (irq_status != MTK_DP_HPD_INTERRUPT) { + mtk_dp->irq_thread_handle |= MTK_DP_THREAD_CABLE_STATE_CHG; + cable_sta_chg = true; + } + + spin_unlock_irqrestore(&mtk_dp->irq_thread_lock, flags); + + if (cable_sta_chg) { + if (!!(mtk_dp_read(mtk_dp, MTK_DP_TRANS_P0_3414) & + HPD_DB_DP_TRANS_P0_MASK)) + mtk_dp->train_info.cable_plugged_in = true; + else + mtk_dp->train_info.cable_plugged_in = false; + } + + return IRQ_WAKE_THREAD; +} + +static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, + struct platform_device *pdev) +{ + struct device_node *endpoint; + struct device *dev = &pdev->dev; + int ret; + void __iomem *base; + u32 linkrate; + int len; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + mtk_dp->regs = devm_regmap_init_mmio(dev, base, &mtk_dp_regmap_config); + if (IS_ERR(mtk_dp->regs)) + return PTR_ERR(mtk_dp->regs); + + endpoint = of_graph_get_endpoint_by_regs(pdev->dev.of_node, 1, -1); + len = of_property_count_elems_of_size(endpoint, + "data-lanes", sizeof(u32)); + if (len < 0 || len > 4 || len == 3) { + dev_err(dev, "invalid data lane size: %d\n", len); + return -EINVAL; + } + + mtk_dp->max_lanes = len; + + ret = device_property_read_u32(dev, "max-linkrate-mhz", &linkrate); + if (ret) { + dev_err(dev, "failed to read max linkrate: %d\n", ret); + return ret; + } + + mtk_dp->max_linkrate = drm_dp_link_rate_to_bw_code(linkrate * 100); + + return 0; +} + +static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + bool enabled = mtk_dp->enabled; + struct edid *new_edid = NULL; + + if (!enabled) { + drm_bridge_chain_pre_enable(bridge); + + /* power on aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL_LANE, + DP_PWR_STATE_MASK); + + /* power on panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + usleep_range(2000, 5000); + } + + new_edid = drm_get_edid(connector, &mtk_dp->aux.ddc); + + /* + * Parse capability here to let atomic_get_input_bus_fmts and + * mode_valid use the capability to calculate sink bitrates. + */ + if (mtk_dp_parse_capabilities(mtk_dp)) { + drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n"); + new_edid = NULL; + } + + if (!enabled) { + /* power off panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); + usleep_range(2000, 3000); + + /* power off aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); + + drm_bridge_chain_post_disable(bridge); + } + + return new_edid; +} + +static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, + struct drm_dp_aux_msg *msg) +{ + struct mtk_dp *mtk_dp; + bool is_read; + u8 request; + size_t accessed_bytes = 0; + int ret; + + mtk_dp = container_of(mtk_aux, struct mtk_dp, aux); + + if (!mtk_dp->train_info.cable_plugged_in) { + ret = -EAGAIN; + goto err; + } + + switch (msg->request) { + case DP_AUX_I2C_MOT: + case DP_AUX_I2C_WRITE: + case DP_AUX_NATIVE_WRITE: + case DP_AUX_I2C_WRITE_STATUS_UPDATE: + case DP_AUX_I2C_WRITE_STATUS_UPDATE | DP_AUX_I2C_MOT: + request = msg->request & ~DP_AUX_I2C_WRITE_STATUS_UPDATE; + is_read = false; + break; + case DP_AUX_I2C_READ: + case DP_AUX_NATIVE_READ: + case DP_AUX_I2C_READ | DP_AUX_I2C_MOT: + request = msg->request; + is_read = true; + break; + default: + drm_err(mtk_aux->drm_dev, "invalid aux cmd = %d\n", + msg->request); + ret = -EINVAL; + goto err; + } + + do { + size_t to_access = min_t(size_t, DP_AUX_MAX_PAYLOAD_BYTES, + msg->size - accessed_bytes); + + ret = mtk_dp_aux_do_transfer(mtk_dp, is_read, request, + msg->address + accessed_bytes, + msg->buffer + accessed_bytes, + to_access); + + if (ret) { + drm_info(mtk_dp->drm_dev, + "Failed to do AUX transfer: %d\n", ret); + goto err; + } + accessed_bytes += to_access; + } while (accessed_bytes < msg->size); + + msg->reply = DP_AUX_NATIVE_REPLY_ACK | DP_AUX_I2C_REPLY_ACK; + return msg->size; +err: + msg->reply = DP_AUX_NATIVE_REPLY_NACK | DP_AUX_I2C_REPLY_NACK; + return ret; +} + +static int mtk_dp_poweron(struct mtk_dp *mtk_dp) +{ + int ret; + + ret = phy_init(mtk_dp->phy); + if (ret) { + dev_err(mtk_dp->dev, "Failed to initialize phy: %d\n", ret); + return ret; + } + + mtk_dp_init_port(mtk_dp); + mtk_dp_power_enable(mtk_dp); + + return 0; +} + +static void mtk_dp_poweroff(struct mtk_dp *mtk_dp) +{ + mtk_dp_power_disable(mtk_dp); + phy_exit(mtk_dp->phy); +} + +static int mtk_dp_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + int ret; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + dev_err(mtk_dp->dev, "Driver does not provide a connector!"); + return -EINVAL; + } + + mtk_dp->aux.drm_dev = bridge->dev; + ret = drm_dp_aux_register(&mtk_dp->aux); + if (ret) { + dev_err(mtk_dp->dev, + "failed to register DP AUX channel: %d\n", ret); + return ret; + } + + ret = mtk_dp_poweron(mtk_dp); + if (ret) + goto err_aux_register; + + if (mtk_dp->next_bridge) { + ret = drm_bridge_attach(bridge->encoder, mtk_dp->next_bridge, + &mtk_dp->bridge, flags); + if (ret) { + drm_warn(mtk_dp->drm_dev, + "Failed to attach external bridge: %d\n", ret); + goto err_bridge_attach; + } + } + + mtk_dp->drm_dev = bridge->dev; + + mtk_dp_hwirq_enable(mtk_dp, true); + + return 0; + +err_bridge_attach: + mtk_dp_poweroff(mtk_dp); +err_aux_register: + drm_dp_aux_unregister(&mtk_dp->aux); + return ret; +} + +static void mtk_dp_bridge_detach(struct drm_bridge *bridge) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + + mtk_dp_hwirq_enable(mtk_dp, false); + mtk_dp->drm_dev = NULL; + mtk_dp_poweroff(mtk_dp); + drm_dp_aux_unregister(&mtk_dp->aux); +} + +static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_state) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + int ret; + + mtk_dp->conn = drm_atomic_get_new_connector_for_encoder(old_state->base.state, + bridge->encoder); + if (!mtk_dp->conn) { + drm_err(mtk_dp->drm_dev, + "Can't enable bridge as connector is missing\n"); + return; + } + + /* power on aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL_LANE, + DP_PWR_STATE_MASK); + + if (mtk_dp->train_info.cable_plugged_in) { + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + usleep_range(2000, 5000); + } + + /* Training */ + ret = mtk_dp_training(mtk_dp); + if (ret) { + drm_err(mtk_dp->drm_dev, "Training failed, %d\n", ret); + goto power_off_aux; + } + + ret = mtk_dp_video_config(mtk_dp); + if (ret) + goto power_off_aux; + + mtk_dp_video_enable(mtk_dp, true); + + mtk_dp->enabled = true; + + return; +power_off_aux: + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); +} + +static void mtk_dp_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_state) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + + mtk_dp->enabled = false; + mtk_dp_video_enable(mtk_dp, false); + + if (mtk_dp->train_info.cable_plugged_in) { + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); + usleep_range(2000, 3000); + } + + /* power off aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); + + /* Ensure the sink is muted */ + msleep(20); +} + +static enum drm_mode_status +mtk_dp_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + u32 bpp = info->color_formats & DRM_COLOR_FORMAT_YCBCR422 ? 16 : 24; + u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) * + drm_dp_max_lane_count(mtk_dp->rx_cap), + drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) * + mtk_dp->max_lanes); + + if (rate < mode->clock * bpp / 8) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static u32 *mtk_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + unsigned int *num_output_fmts) +{ + u32 *output_fmts; + + *num_output_fmts = 0; + output_fmts = kmalloc(sizeof(*output_fmts), GFP_KERNEL); + if (!output_fmts) + return NULL; + *num_output_fmts = 1; + output_fmts[0] = MEDIA_BUS_FMT_FIXED; + return output_fmts; +} + +static const u32 mt8195_input_fmts[] = { + MEDIA_BUS_FMT_RGB888_1X24, + MEDIA_BUS_FMT_YUV8_1X24, + MEDIA_BUS_FMT_YUYV8_1X16, +}; + +static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + u32 *input_fmts; + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + struct drm_display_mode *mode = &crtc_state->adjusted_mode; + struct drm_display_info *display_info = + &conn_state->connector->display_info; + u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) * + drm_dp_max_lane_count(mtk_dp->rx_cap), + drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) * + mtk_dp->max_lanes); + + *num_input_fmts = 0; + + /* + * If the linkrate is smaller than datarate of RGB888, larger than + * datarate of YUV422 and sink device supports YUV422, we output YUV422 + * format. Use this condition, we can support more resolution. + */ + if ((rate < (mode->clock * 24 / 8)) && + (rate > (mode->clock * 16 / 8)) && + (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { + input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) + return NULL; + *num_input_fmts = 1; + input_fmts[0] = MEDIA_BUS_FMT_YUYV8_1X16; + } else { + input_fmts = kcalloc(ARRAY_SIZE(mt8195_input_fmts), + sizeof(*input_fmts), + GFP_KERNEL); + if (!input_fmts) + return NULL; + + *num_input_fmts = ARRAY_SIZE(mt8195_input_fmts); + memcpy(input_fmts, mt8195_input_fmts, sizeof(mt8195_input_fmts)); + } + + return input_fmts; +} + +static int mtk_dp_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + struct drm_crtc *crtc = conn_state->crtc; + unsigned int input_bus_format; + + input_bus_format = bridge_state->input_bus_cfg.format; + + dev_dbg(mtk_dp->dev, "input format 0x%04x, output format 0x%04x\n", + bridge_state->input_bus_cfg.format, + bridge_state->output_bus_cfg.format); + + if (input_bus_format == MEDIA_BUS_FMT_YUYV8_1X16) + mtk_dp->info.format = DP_PIXELFORMAT_YUV422; + else + mtk_dp->info.format = DP_PIXELFORMAT_RGB; + + if (!crtc) { + drm_err(mtk_dp->drm_dev, + "Can't enable bridge as connector state doesn't have a crtc\n"); + return -EINVAL; + } + + drm_display_mode_to_videomode(&crtc_state->adjusted_mode, &mtk_dp->info.vm); + + return 0; +} + +static const struct drm_bridge_funcs mtk_dp_bridge_funcs = { + .atomic_check = mtk_dp_bridge_atomic_check, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_get_output_bus_fmts = mtk_dp_bridge_atomic_get_output_bus_fmts, + .atomic_get_input_bus_fmts = mtk_dp_bridge_atomic_get_input_bus_fmts, + .atomic_reset = drm_atomic_helper_bridge_reset, + .attach = mtk_dp_bridge_attach, + .detach = mtk_dp_bridge_detach, + .atomic_enable = mtk_dp_bridge_atomic_enable, + .atomic_disable = mtk_dp_bridge_atomic_disable, + .mode_valid = mtk_dp_bridge_mode_valid, + .get_edid = mtk_dp_get_edid, +}; + +static int mtk_dp_probe(struct platform_device *pdev) +{ + struct mtk_dp *mtk_dp; + struct device *dev = &pdev->dev; + int ret, irq_num; + + mtk_dp = devm_kzalloc(dev, sizeof(*mtk_dp), GFP_KERNEL); + if (!mtk_dp) + return -ENOMEM; + + mtk_dp->dev = dev; + + irq_num = platform_get_irq(pdev, 0); + if (irq_num < 0) + return dev_err_probe(dev, irq_num, + "failed to request dp irq resource\n"); + + mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); + if (IS_ERR(mtk_dp->next_bridge)) + return dev_err_probe(dev, PTR_ERR(mtk_dp->next_bridge), + "Failed to get bridge\n"); + + ret = mtk_dp_dt_parse(mtk_dp, pdev); + if (ret) + return dev_err_probe(dev, ret, "Failed to parse dt\n"); + + drm_dp_aux_init(&mtk_dp->aux); + mtk_dp->aux.name = "aux_mtk_dp"; + mtk_dp->aux.transfer = mtk_dp_aux_transfer; + + spin_lock_init(&mtk_dp->irq_thread_lock); + + ret = devm_request_threaded_irq(dev, irq_num, mtk_dp_hpd_event, + mtk_dp_hpd_event_thread, + IRQ_TYPE_LEVEL_HIGH, dev_name(dev), + mtk_dp); + if (ret) + return dev_err_probe(dev, ret, + "failed to request mediatek dptx irq\n"); + + platform_set_drvdata(pdev, mtk_dp); + + mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy", + PLATFORM_DEVID_AUTO, + &mtk_dp->regs, + sizeof(struct regmap *)); + if (IS_ERR(mtk_dp->phy_dev)) + return dev_err_probe(dev, PTR_ERR(mtk_dp->phy_dev), + "Failed to create device mediatek-dp-phy\n"); + + mtk_dp_get_calibration_data(mtk_dp); + + mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp"); + + if (IS_ERR(mtk_dp->phy)) { + platform_device_unregister(mtk_dp->phy_dev); + return dev_err_probe(dev, PTR_ERR(mtk_dp->phy), + "Failed to get phy\n"); + } + + mtk_dp->bridge.funcs = &mtk_dp_bridge_funcs; + mtk_dp->bridge.of_node = dev->of_node; + + mtk_dp->bridge.ops = + DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; + mtk_dp->bridge.type = DRM_MODE_CONNECTOR_eDP; + + drm_bridge_add(&mtk_dp->bridge); + + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + return 0; +} + +static int mtk_dp_remove(struct platform_device *pdev) +{ + struct mtk_dp *mtk_dp = platform_get_drvdata(pdev); + + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + drm_bridge_remove(&mtk_dp->bridge); + platform_device_unregister(mtk_dp->phy_dev); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mtk_dp_suspend(struct device *dev) +{ + struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + + mtk_dp_power_disable(mtk_dp); + mtk_dp_hwirq_enable(mtk_dp, false); + pm_runtime_put_sync(dev); + + return 0; +} + +static int mtk_dp_resume(struct device *dev) +{ + struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + + pm_runtime_get_sync(dev); + mtk_dp_init_port(mtk_dp); + mtk_dp_hwirq_enable(mtk_dp, true); + mtk_dp_power_enable(mtk_dp); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mtk_dp_pm_ops, mtk_dp_suspend, mtk_dp_resume); + +static const struct of_device_id mtk_dp_of_match[] = { + { .compatible = "mediatek,mt8195-edp-tx" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mtk_dp_of_match); + +struct platform_driver mtk_dp_driver = { + .probe = mtk_dp_probe, + .remove = mtk_dp_remove, + .driver = { + .name = "mediatek-drm-dp", + .of_match_table = mtk_dp_of_match, + .pm = &mtk_dp_pm_ops, + }, +}; + +module_platform_driver(mtk_dp_driver); + +MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>"); +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>"); +MODULE_AUTHOR("Bo-Chen Chen <rex-bc.chen@mediatek.com>"); +MODULE_DESCRIPTION("MediaTek DisplayPort Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/mediatek/mtk_dp_reg.h b/drivers/gpu/drm/mediatek/mtk_dp_reg.h new file mode 100644 index 000000000000..3f01ba44871f --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_dp_reg.h @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019-2022 MediaTek Inc. + * Copyright (c) 2022 BayLibre + */ +#ifndef _MTK_DP_REG_H_ +#define _MTK_DP_REG_H_ + +#define SEC_OFFSET 0x4000 + +#define MTK_DP_HPD_DISCONNECT BIT(1) +#define MTK_DP_HPD_CONNECT BIT(2) +#define MTK_DP_HPD_INTERRUPT BIT(3) + +/* offset: 0x0 */ +#define DP_PHY_GLB_BIAS_GEN_00 0x0 +#define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(20, 16) +#define DP_PHY_GLB_DPAUX_TX 0x8 +#define RG_CKM_PT0_CKTX_IMPSEL GENMASK(23, 20) +#define MTK_DP_0034 0x34 +#define DA_XTP_GLB_CKDET_EN_FORCE_VAL BIT(15) +#define DA_XTP_GLB_CKDET_EN_FORCE_EN BIT(14) +#define DA_CKM_INTCKTX_EN_FORCE_VAL BIT(13) +#define DA_CKM_INTCKTX_EN_FORCE_EN BIT(12) +#define DA_CKM_CKTX0_EN_FORCE_VAL BIT(11) +#define DA_CKM_CKTX0_EN_FORCE_EN BIT(10) +#define DA_CKM_XTAL_CK_FORCE_VAL BIT(9) +#define DA_CKM_XTAL_CK_FORCE_EN BIT(8) +#define DA_CKM_BIAS_LPF_EN_FORCE_VAL BIT(7) +#define DA_CKM_BIAS_LPF_EN_FORCE_EN BIT(6) +#define DA_CKM_BIAS_EN_FORCE_VAL BIT(5) +#define DA_CKM_BIAS_EN_FORCE_EN BIT(4) +#define DA_XTP_GLB_AVD10_ON_FORCE_VAL BIT(3) +#define DA_XTP_GLB_AVD10_ON_FORCE BIT(2) +#define DA_XTP_GLB_LDO_EN_FORCE_VAL BIT(1) +#define DA_XTP_GLB_LDO_EN_FORCE_EN BIT(0) +#define DP_PHY_LANE_TX_0 0x104 +#define RG_XTP_LN0_TX_IMPSEL_PMOS GENMASK(15, 12) +#define RG_XTP_LN0_TX_IMPSEL_NMOS GENMASK(19, 16) +#define DP_PHY_LANE_TX_1 0x204 +#define RG_XTP_LN1_TX_IMPSEL_PMOS GENMASK(15, 12) +#define RG_XTP_LN1_TX_IMPSEL_NMOS GENMASK(19, 16) +#define DP_PHY_LANE_TX_2 0x304 +#define RG_XTP_LN2_TX_IMPSEL_PMOS GENMASK(15, 12) +#define RG_XTP_LN2_TX_IMPSEL_NMOS GENMASK(19, 16) +#define DP_PHY_LANE_TX_3 0x404 +#define RG_XTP_LN3_TX_IMPSEL_PMOS GENMASK(15, 12) +#define RG_XTP_LN3_TX_IMPSEL_NMOS GENMASK(19, 16) +#define MTK_DP_1040 0x1040 +#define RG_DPAUX_RX_VALID_DEGLITCH_EN BIT(2) +#define RG_XTP_GLB_CKDET_EN BIT(1) +#define RG_DPAUX_RX_EN BIT(0) + +/* offset: TOP_OFFSET (0x2000) */ +#define MTK_DP_TOP_PWR_STATE 0x2000 +#define DP_PWR_STATE_MASK GENMASK(1, 0) +#define DP_PWR_STATE_BANDGAP BIT(0) +#define DP_PWR_STATE_BANDGAP_TPLL BIT(1) +#define DP_PWR_STATE_BANDGAP_TPLL_LANE GENMASK(1, 0) +#define MTK_DP_TOP_SWING_EMP 0x2004 +#define DP_TX0_VOLT_SWING_MASK GENMASK(1, 0) +#define DP_TX0_VOLT_SWING_SHIFT 0 +#define DP_TX0_PRE_EMPH_MASK GENMASK(3, 2) +#define DP_TX0_PRE_EMPH_SHIFT 2 +#define DP_TX1_VOLT_SWING_MASK GENMASK(9, 8) +#define DP_TX1_VOLT_SWING_SHIFT 8 +#define DP_TX1_PRE_EMPH_MASK GENMASK(11, 10) +#define DP_TX2_VOLT_SWING_MASK GENMASK(17, 16) +#define DP_TX2_PRE_EMPH_MASK GENMASK(19, 18) +#define DP_TX3_VOLT_SWING_MASK GENMASK(25, 24) +#define DP_TX3_PRE_EMPH_MASK GENMASK(27, 26) +#define MTK_DP_TOP_RESET_AND_PROBE 0x2020 +#define SW_RST_B_PHYD BIT(4) +#define MTK_DP_TOP_IRQ_MASK 0x202c +#define IRQ_MASK_AUX_TOP_IRQ BIT(2) +#define MTK_DP_TOP_MEM_PD 0x2038 +#define MEM_ISO_EN BIT(0) +#define FUSE_SEL BIT(2) + +/* offset: ENC0_OFFSET (0x3000) */ +#define MTK_DP_ENC0_P0_3000 0x3000 +#define LANE_NUM_DP_ENC0_P0_MASK GENMASK(1, 0) +#define VIDEO_MUTE_SW_DP_ENC0_P0 BIT(2) +#define VIDEO_MUTE_SEL_DP_ENC0_P0 BIT(3) +#define ENHANCED_FRAME_EN_DP_ENC0_P0 BIT(4) +#define MTK_DP_ENC0_P0_3004 0x3004 +#define VIDEO_M_CODE_SEL_DP_ENC0_P0_MASK BIT(8) +#define DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0 BIT(9) +#define MTK_DP_ENC0_P0_3010 0x3010 +#define HTOTAL_SW_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3014 0x3014 +#define VTOTAL_SW_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3018 0x3018 +#define HSTART_SW_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_301C 0x301c +#define VSTART_SW_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3020 0x3020 +#define HWIDTH_SW_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3024 0x3024 +#define VHEIGHT_SW_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3028 0x3028 +#define HSW_SW_DP_ENC0_P0_MASK GENMASK(14, 0) +#define HSP_SW_DP_ENC0_P0_MASK BIT(15) +#define MTK_DP_ENC0_P0_302C 0x302c +#define VSW_SW_DP_ENC0_P0_MASK GENMASK(14, 0) +#define VSP_SW_DP_ENC0_P0_MASK BIT(15) +#define MTK_DP_ENC0_P0_3030 0x3030 +#define HTOTAL_SEL_DP_ENC0_P0 BIT(0) +#define VTOTAL_SEL_DP_ENC0_P0 BIT(1) +#define HSTART_SEL_DP_ENC0_P0 BIT(2) +#define VSTART_SEL_DP_ENC0_P0 BIT(3) +#define HWIDTH_SEL_DP_ENC0_P0 BIT(4) +#define VHEIGHT_SEL_DP_ENC0_P0 BIT(5) +#define HSP_SEL_DP_ENC0_P0 BIT(6) +#define HSW_SEL_DP_ENC0_P0 BIT(7) +#define VSP_SEL_DP_ENC0_P0 BIT(8) +#define VSW_SEL_DP_ENC0_P0 BIT(9) +#define MTK_DP_ENC0_P0_3034 0x3034 +#define MTK_DP_ENC0_P0_3038 0x3038 +#define VIDEO_SOURCE_SEL_DP_ENC0_P0_MASK BIT(11) +#define MTK_DP_ENC0_P0_303C 0x303c +#define SRAM_START_READ_THRD_DP_ENC0_P0_MASK GENMASK(5, 0) +#define VIDEO_COLOR_DEPTH_DP_ENC0_P0_MASK GENMASK(10, 8) +#define VIDEO_COLOR_DEPTH_DP_ENC0_P0_16BIT (0 << 8) +#define VIDEO_COLOR_DEPTH_DP_ENC0_P0_12BIT (1 << 8) +#define VIDEO_COLOR_DEPTH_DP_ENC0_P0_10BIT (2 << 8) +#define VIDEO_COLOR_DEPTH_DP_ENC0_P0_8BIT (3 << 8) +#define VIDEO_COLOR_DEPTH_DP_ENC0_P0_6BIT (4 << 8) +#define PIXEL_ENCODE_FORMAT_DP_ENC0_P0_MASK GENMASK(14, 12) +#define PIXEL_ENCODE_FORMAT_DP_ENC0_P0_RGB (0 << 12) +#define PIXEL_ENCODE_FORMAT_DP_ENC0_P0_YCBCR422 (1 << 12) +#define PIXEL_ENCODE_FORMAT_DP_ENC0_P0_YCBCR420 (2 << 12) +#define VIDEO_MN_GEN_EN_DP_ENC0_P0 BIT(15) +#define MTK_DP_ENC0_P0_3040 0x3040 +#define SDP_DOWN_CNT_DP_ENC0_P0_VAL 0x20 +#define SDP_DOWN_CNT_INIT_DP_ENC0_P0_MASK GENMASK(11, 0) +#define MTK_DP_ENC0_P0_304C 0x304c +#define VBID_VIDEO_MUTE_DP_ENC0_P0_MASK BIT(2) +#define SDP_VSYNC_RISING_MASK_DP_ENC0_P0_MASK BIT(8) +#define MTK_DP_ENC0_P0_3064 0x3064 +#define HDE_NUM_LAST_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3154 0x3154 +#define PGEN_HTOTAL_DP_ENC0_P0_MASK GENMASK(13, 0) +#define MTK_DP_ENC0_P0_3158 0x3158 +#define PGEN_HSYNC_RISING_DP_ENC0_P0_MASK GENMASK(13, 0) +#define MTK_DP_ENC0_P0_315C 0x315c +#define PGEN_HSYNC_PULSE_WIDTH_DP_ENC0_P0_MASK GENMASK(13, 0) +#define MTK_DP_ENC0_P0_3160 0x3160 +#define PGEN_HFDE_START_DP_ENC0_P0_MASK GENMASK(13, 0) +#define MTK_DP_ENC0_P0_3164 0x3164 +#define PGEN_HFDE_ACTIVE_WIDTH_DP_ENC0_P0_MASK GENMASK(13, 0) +#define MTK_DP_ENC0_P0_3168 0x3168 +#define PGEN_VTOTAL_DP_ENC0_P0_MASK GENMASK(12, 0) +#define MTK_DP_ENC0_P0_316C 0x316c +#define PGEN_VSYNC_RISING_DP_ENC0_P0_MASK GENMASK(12, 0) +#define MTK_DP_ENC0_P0_3170 0x3170 +#define PGEN_VSYNC_PULSE_WIDTH_DP_ENC0_P0_MASK GENMASK(12, 0) +#define MTK_DP_ENC0_P0_3174 0x3174 +#define PGEN_VFDE_START_DP_ENC0_P0_MASK GENMASK(12, 0) +#define MTK_DP_ENC0_P0_3178 0x3178 +#define PGEN_VFDE_ACTIVE_WIDTH_DP_ENC0_P0_MASK GENMASK(12, 0) +#define MTK_DP_ENC0_P0_31B0 0x31b0 +#define PGEN_PATTERN_SEL_VAL 4 +#define PGEN_PATTERN_SEL_MASK GENMASK(6, 4) +#define MTK_DP_ENC0_P0_31EC 0x31ec +#define AUDIO_CH_SRC_SEL_DP_ENC0_P0 BIT(4) +#define ISRC1_HB3_DP_ENC0_P0_MASK GENMASK(15, 8) + +/* offset: ENC1_OFFSET (0x3200) */ +#define MTK_DP_ENC1_P0_3300 0x3300 +#define VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_VAL 2 +#define VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_MASK GENMASK(9, 8) +#define MTK_DP_ENC1_P0_3364 0x3364 +#define SDP_DOWN_CNT_IN_HBLANK_DP_ENC1_P0_VAL 0x20 +#define SDP_DOWN_CNT_INIT_IN_HBLANK_DP_ENC1_P0_MASK GENMASK(11, 0) +#define FIFO_READ_START_POINT_DP_ENC1_P0_VAL 4 +#define FIFO_READ_START_POINT_DP_ENC1_P0_MASK GENMASK(15, 12) +#define MTK_DP_ENC1_P0_3368 0x3368 +#define VIDEO_SRAM_FIFO_CNT_RESET_SEL_DP_ENC1_P0 BIT(0) +#define VIDEO_STABLE_CNT_THRD_DP_ENC1_P0 BIT(4) +#define SDP_DP13_EN_DP_ENC1_P0 BIT(8) +#define BS2BS_MODE_DP_ENC1_P0 BIT(12) +#define BS2BS_MODE_DP_ENC1_P0_MASK GENMASK(13, 12) +#define BS2BS_MODE_DP_ENC1_P0_VAL 1 +#define DP_ENC1_P0_3368_VAL (VIDEO_SRAM_FIFO_CNT_RESET_SEL_DP_ENC1_P0 | \ + VIDEO_STABLE_CNT_THRD_DP_ENC1_P0 | \ + SDP_DP13_EN_DP_ENC1_P0 | \ + BS2BS_MODE_DP_ENC1_P0) + +/* offset: TRANS_OFFSET (0x3400) */ +#define MTK_DP_TRANS_P0_3400 0x3400 +#define PATTERN1_EN_DP_TRANS_P0_MASK BIT(12) +#define PATTERN2_EN_DP_TRANS_P0_MASK BIT(13) +#define PATTERN3_EN_DP_TRANS_P0_MASK BIT(14) +#define PATTERN4_EN_DP_TRANS_P0_MASK BIT(15) +#define MTK_DP_TRANS_P0_3404 0x3404 +#define DP_SCR_EN_DP_TRANS_P0_MASK BIT(0) +#define MTK_DP_TRANS_P0_340C 0x340c +#define DP_TX_TRANSMITTER_4P_RESET_SW_DP_TRANS_P0 BIT(13) +#define MTK_DP_TRANS_P0_3410 0x3410 +#define HPD_DEB_THD_DP_TRANS_P0_MASK GENMASK(3, 0) +#define HPD_INT_THD_DP_TRANS_P0_MASK GENMASK(7, 4) +#define HPD_INT_THD_DP_TRANS_P0_LOWER_500US (2 << 4) +#define HPD_INT_THD_DP_TRANS_P0_UPPER_1100US (2 << 6) +#define HPD_DISC_THD_DP_TRANS_P0_MASK GENMASK(11, 8) +#define HPD_CONN_THD_DP_TRANS_P0_MASK GENMASK(15, 12) +#define MTK_DP_TRANS_P0_3414 0x3414 +#define HPD_DB_DP_TRANS_P0_MASK BIT(2) +#define MTK_DP_TRANS_P0_3418 0x3418 +#define IRQ_CLR_DP_TRANS_P0_MASK GENMASK(3, 0) +#define IRQ_MASK_DP_TRANS_P0_MASK GENMASK(7, 4) +#define IRQ_MASK_DP_TRANS_P0_DISC_IRQ (BIT(1) << 4) +#define IRQ_MASK_DP_TRANS_P0_CONN_IRQ (BIT(2) << 4) +#define IRQ_MASK_DP_TRANS_P0_INT_IRQ (BIT(3) << 4) +#define IRQ_STATUS_DP_TRANS_P0_MASK GENMASK(15, 12) +#define MTK_DP_TRANS_P0_342C 0x342c +#define XTAL_FREQ_DP_TRANS_P0_DEFAULT (BIT(0) | BIT(3) | BIT(5) | BIT(6)) +#define XTAL_FREQ_DP_TRANS_P0_MASK GENMASK(7, 0) +#define MTK_DP_TRANS_P0_3430 0x3430 +#define HPD_INT_THD_ECO_DP_TRANS_P0_MASK GENMASK(1, 0) +#define HPD_INT_THD_ECO_DP_TRANS_P0_HIGH_BOUND_EXT BIT(1) +#define MTK_DP_TRANS_P0_34A4 0x34a4 +#define LANE_NUM_DP_TRANS_P0_MASK GENMASK(3, 2) +#define MTK_DP_TRANS_P0_3540 0x3540 +#define FEC_EN_DP_TRANS_P0_MASK BIT(0) +#define FEC_CLOCK_EN_MODE_DP_TRANS_P0 BIT(3) +#define MTK_DP_TRANS_P0_3580 0x3580 +#define POST_MISC_DATA_LANE0_OV_DP_TRANS_P0_MASK BIT(8) +#define POST_MISC_DATA_LANE1_OV_DP_TRANS_P0_MASK BIT(9) +#define POST_MISC_DATA_LANE2_OV_DP_TRANS_P0_MASK BIT(10) +#define POST_MISC_DATA_LANE3_OV_DP_TRANS_P0_MASK BIT(11) +#define MTK_DP_TRANS_P0_35C8 0x35c8 +#define SW_IRQ_CLR_DP_TRANS_P0_MASK GENMASK(15, 0) +#define SW_IRQ_STATUS_DP_TRANS_P0_MASK GENMASK(15, 0) +#define MTK_DP_TRANS_P0_35D0 0x35d0 +#define SW_IRQ_FINAL_STATUS_DP_TRANS_P0_MASK GENMASK(15, 0) +#define MTK_DP_TRANS_P0_35F0 0x35f0 +#define DP_TRANS_DUMMY_RW_0 BIT(3) +#define DP_TRANS_DUMMY_RW_0_MASK GENMASK(3, 2) + +/* offset: AUX_OFFSET (0x3600) */ +#define MTK_DP_AUX_P0_360C 0x360c +#define AUX_TIMEOUT_THR_AUX_TX_P0_MASK GENMASK(12, 0) +#define AUX_TIMEOUT_THR_AUX_TX_P0_VAL 0x1595 +#define MTK_DP_AUX_P0_3614 0x3614 +#define AUX_RX_UI_CNT_THR_AUX_TX_P0_MASK GENMASK(6, 0) +#define AUX_RX_UI_CNT_THR_AUX_FOR_26M 13 +#define MTK_DP_AUX_P0_3618 0x3618 +#define AUX_RX_FIFO_FULL_AUX_TX_P0_MASK BIT(9) +#define AUX_RX_FIFO_WRITE_POINTER_AUX_TX_P0_MASK GENMASK(3, 0) +#define MTK_DP_AUX_P0_3620 0x3620 +#define AUX_RD_MODE_AUX_TX_P0_MASK BIT(9) +#define AUX_RX_FIFO_READ_PULSE_TX_P0 BIT(8) +#define AUX_RX_FIFO_READ_DATA_AUX_TX_P0_MASK GENMASK(7, 0) +#define MTK_DP_AUX_P0_3624 0x3624 +#define AUX_RX_REPLY_COMMAND_AUX_TX_P0_MASK GENMASK(3, 0) +#define MTK_DP_AUX_P0_3628 0x3628 +#define AUX_RX_PHY_STATE_AUX_TX_P0_MASK GENMASK(9, 0) +#define AUX_RX_PHY_STATE_AUX_TX_P0_RX_IDLE BIT(0) +#define MTK_DP_AUX_P0_362C 0x362c +#define AUX_NO_LENGTH_AUX_TX_P0 BIT(0) +#define AUX_TX_AUXTX_OV_EN_AUX_TX_P0_MASK BIT(1) +#define AUX_RESERVED_RW_0_AUX_TX_P0_MASK GENMASK(15, 2) +#define MTK_DP_AUX_P0_3630 0x3630 +#define AUX_TX_REQUEST_READY_AUX_TX_P0 BIT(3) +#define MTK_DP_AUX_P0_3634 0x3634 +#define AUX_TX_OVER_SAMPLE_RATE_AUX_TX_P0_MASK GENMASK(15, 8) +#define AUX_TX_OVER_SAMPLE_RATE_FOR_26M 25 +#define MTK_DP_AUX_P0_3640 0x3640 +#define AUX_RX_AUX_RECV_COMPLETE_IRQ_AUX_TX_P0 BIT(6) +#define AUX_RX_EDID_RECV_COMPLETE_IRQ_AUX_TX_P0 BIT(5) +#define AUX_RX_MCCS_RECV_COMPLETE_IRQ_AUX_TX_P0 BIT(4) +#define AUX_RX_CMD_RECV_IRQ_AUX_TX_P0 BIT(3) +#define AUX_RX_ADDR_RECV_IRQ_AUX_TX_P0 BIT(2) +#define AUX_RX_DATA_RECV_IRQ_AUX_TX_P0 BIT(1) +#define AUX_400US_TIMEOUT_IRQ_AUX_TX_P0 BIT(0) +#define DP_AUX_P0_3640_VAL (AUX_400US_TIMEOUT_IRQ_AUX_TX_P0 | \ + AUX_RX_DATA_RECV_IRQ_AUX_TX_P0 | \ + AUX_RX_ADDR_RECV_IRQ_AUX_TX_P0 | \ + AUX_RX_CMD_RECV_IRQ_AUX_TX_P0 | \ + AUX_RX_MCCS_RECV_COMPLETE_IRQ_AUX_TX_P0 | \ + AUX_RX_EDID_RECV_COMPLETE_IRQ_AUX_TX_P0 | \ + AUX_RX_AUX_RECV_COMPLETE_IRQ_AUX_TX_P0) +#define MTK_DP_AUX_P0_3644 0x3644 +#define MCU_REQUEST_COMMAND_AUX_TX_P0_MASK GENMASK(3, 0) +#define MTK_DP_AUX_P0_3648 0x3648 +#define MCU_REQUEST_ADDRESS_LSB_AUX_TX_P0_MASK GENMASK(15, 0) +#define MTK_DP_AUX_P0_364C 0x364c +#define MCU_REQUEST_ADDRESS_MSB_AUX_TX_P0_MASK GENMASK(3, 0) +#define MTK_DP_AUX_P0_3650 0x3650 +#define MCU_REQ_DATA_NUM_AUX_TX_P0_MASK GENMASK(15, 12) +#define PHY_FIFO_RST_AUX_TX_P0_MASK BIT(9) +#define MCU_ACK_TRAN_COMPLETE_AUX_TX_P0 BIT(8) +#define MTK_DP_AUX_P0_3658 0x3658 +#define AUX_TX_OV_EN_AUX_TX_P0_MASK BIT(0) +#define MTK_DP_AUX_P0_3690 0x3690 +#define RX_REPLY_COMPLETE_MODE_AUX_TX_P0 BIT(8) +#define MTK_DP_AUX_P0_3704 0x3704 +#define AUX_TX_FIFO_WDATA_NEW_MODE_T_AUX_TX_P0_MASK BIT(1) +#define AUX_TX_FIFO_NEW_MODE_EN_AUX_TX_P0 BIT(2) +#define MTK_DP_AUX_P0_3708 0x3708 +#define MTK_DP_AUX_P0_37C8 0x37c8 +#define MTK_ATOP_EN_AUX_TX_P0 BIT(0) + +#endif /*_MTK_DP_REG_H_*/ From 17881ea4c45335a2401f56e8909fedd392e5f2b4 Mon Sep 17 00:00:00 2001 From: Bo-Chen Chen <rex-bc.chen@mediatek.com> Date: Thu, 1 Sep 2022 12:41:43 +0800 Subject: [PATCH 353/396] drm/mediatek: dp: Add multiple bridge types support The bridge types of eDP and DP are different. We add device data to this driver and add bridge_type to the device data to define them. Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-5-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index e2ec9b02b1aa..2696c1ac1a47 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -101,6 +101,7 @@ struct mtk_dp { struct drm_device *drm_dev; struct drm_dp_aux aux; + const struct mtk_dp_data *data; struct mtk_dp_info info; struct mtk_dp_train_info train_info; @@ -109,6 +110,9 @@ struct mtk_dp { struct regmap *regs; }; +struct mtk_dp_data { + int bridge_type; +}; static const struct mtk_dp_efuse_fmt mtk_dp_efuse_data[MTK_DP_CAL_MAX] = { [MTK_DP_CAL_GLB_BIAS_TRIM] = { .idx = 3, @@ -1871,6 +1875,7 @@ static int mtk_dp_probe(struct platform_device *pdev) return -ENOMEM; mtk_dp->dev = dev; + mtk_dp->data = (struct mtk_dp_data *)of_device_get_match_data(dev); irq_num = platform_get_irq(pdev, 0); if (irq_num < 0) @@ -1925,7 +1930,7 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; - mtk_dp->bridge.type = DRM_MODE_CONNECTOR_eDP; + mtk_dp->bridge.type = mtk_dp->data->bridge_type; drm_bridge_add(&mtk_dp->bridge); @@ -1974,8 +1979,15 @@ static int mtk_dp_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(mtk_dp_pm_ops, mtk_dp_suspend, mtk_dp_resume); +static const struct mtk_dp_data mt8195_edp_data = { + .bridge_type = DRM_MODE_CONNECTOR_eDP, +}; + static const struct of_device_id mtk_dp_of_match[] = { - { .compatible = "mediatek,mt8195-edp-tx" }, + { + .compatible = "mediatek,mt8195-edp-tx", + .data = &mt8195_edp_data, + }, {}, }; MODULE_DEVICE_TABLE(of, mtk_dp_of_match); From 42dbe4a0a988fe7fd971c5b4bba0dfffc748fbfa Mon Sep 17 00:00:00 2001 From: Bo-Chen Chen <rex-bc.chen@mediatek.com> Date: Thu, 1 Sep 2022 12:41:44 +0800 Subject: [PATCH 354/396] drm/mediatek: dp: Add multiple smc commands support The smc commands of eDP and DP are different. We add smc_cmd to the device data to define them. Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-6-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 2696c1ac1a47..971bd744cdb2 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -112,6 +112,7 @@ struct mtk_dp { struct mtk_dp_data { int bridge_type; + unsigned int smc_cmd; }; static const struct mtk_dp_efuse_fmt mtk_dp_efuse_data[MTK_DP_CAL_MAX] = { [MTK_DP_CAL_GLB_BIAS_TRIM] = { @@ -945,11 +946,11 @@ static void mtk_dp_video_mute(struct mtk_dp *mtk_dp, bool enable) VIDEO_MUTE_SW_DP_ENC0_P0); arm_smccc_smc(MTK_DP_SIP_CONTROL_AARCH32, - MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, enable, + mtk_dp->data->smc_cmd, enable, 0, 0, 0, 0, 0, &res); dev_dbg(mtk_dp->dev, "smc cmd: 0x%x, p1: 0x%x, ret: 0x%lx-0x%lx\n", - MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, enable, res.a0, res.a1); + mtk_dp->data->smc_cmd, enable, res.a0, res.a1); } static void mtk_dp_power_enable(struct mtk_dp *mtk_dp) @@ -1981,6 +1982,7 @@ static SIMPLE_DEV_PM_OPS(mtk_dp_pm_ops, mtk_dp_suspend, mtk_dp_resume); static const struct mtk_dp_data mt8195_edp_data = { .bridge_type = DRM_MODE_CONNECTOR_eDP, + .smc_cmd = MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, }; static const struct of_device_id mtk_dp_of_match[] = { From 16075ed148833d7c4feb13bb295bbcb87a7f321e Mon Sep 17 00:00:00 2001 From: Bo-Chen Chen <rex-bc.chen@mediatek.com> Date: Thu, 1 Sep 2022 12:41:45 +0800 Subject: [PATCH 355/396] drm/mediatek: dp: Add multiple calibration data formats support The calibration data formats of eDP and DP are different. We add "const struct mtk_dp_efuse_fmt *efuse_fmt" to the device data to define them. Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-7-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 971bd744cdb2..136e13150281 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -113,8 +113,10 @@ struct mtk_dp { struct mtk_dp_data { int bridge_type; unsigned int smc_cmd; + const struct mtk_dp_efuse_fmt *efuse_fmt; }; -static const struct mtk_dp_efuse_fmt mtk_dp_efuse_data[MTK_DP_CAL_MAX] = { + +static const struct mtk_dp_efuse_fmt mt8195_edp_efuse_fmt[MTK_DP_CAL_MAX] = { [MTK_DP_CAL_GLB_BIAS_TRIM] = { .idx = 3, .shift = 27, @@ -811,7 +813,7 @@ static void mtk_dp_get_calibration_data(struct mtk_dp *mtk_dp) } for (i = 0; i < MTK_DP_CAL_MAX; i++) { - fmt = &mtk_dp_efuse_data[i]; + fmt = &mtk_dp->data->efuse_fmt[i]; cal_data[i] = (buf[fmt->idx] >> fmt->shift) & fmt->mask; if (cal_data[i] < fmt->min_val || cal_data[i] > fmt->max_val) { @@ -827,7 +829,7 @@ static void mtk_dp_get_calibration_data(struct mtk_dp *mtk_dp) use_default_val: dev_warn(mtk_dp->dev, "Use default calibration data\n"); for (i = 0; i < MTK_DP_CAL_MAX; i++) - cal_data[i] = mtk_dp_efuse_data[i].default_val; + cal_data[i] = mtk_dp->data->efuse_fmt[i].default_val; } static void mtk_dp_set_calibration_data(struct mtk_dp *mtk_dp) @@ -1983,6 +1985,7 @@ static SIMPLE_DEV_PM_OPS(mtk_dp_pm_ops, mtk_dp_suspend, mtk_dp_resume); static const struct mtk_dp_data mt8195_edp_data = { .bridge_type = DRM_MODE_CONNECTOR_eDP, .smc_cmd = MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, + .efuse_fmt = mt8195_edp_efuse_fmt, }; static const struct of_device_id mtk_dp_of_match[] = { From 86e77a1f0ae83381796d6b83f5cb33d9c6dcf6e7 Mon Sep 17 00:00:00 2001 From: Bo-Chen Chen <rex-bc.chen@mediatek.com> Date: Thu, 1 Sep 2022 12:41:46 +0800 Subject: [PATCH 356/396] drm/mediatek: dp: Determine device of next_bridge It's not necessary to have a next_bridge for DP device, so we add this patch to judge this. Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-8-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 136e13150281..e37c9185e4ec 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1886,7 +1886,10 @@ static int mtk_dp_probe(struct platform_device *pdev) "failed to request dp irq resource\n"); mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); - if (IS_ERR(mtk_dp->next_bridge)) + if (IS_ERR(mtk_dp->next_bridge) && + PTR_ERR(mtk_dp->next_bridge) == -ENODEV) + mtk_dp->next_bridge = NULL; + else if (IS_ERR(mtk_dp->next_bridge)) return dev_err_probe(dev, PTR_ERR(mtk_dp->next_bridge), "Failed to get bridge\n"); From d9e6ea02fc3f873a33709c3030034e9536230498 Mon Sep 17 00:00:00 2001 From: Guillaume Ranquet <granquet@baylibre.com> Date: Thu, 1 Sep 2022 12:41:47 +0800 Subject: [PATCH 357/396] drm/mediatek: dp: Add MT8195 External DisplayPort support Add External DisplayPort support to the MT8195 eDP driver. Signed-off-by: Guillaume Ranquet <granquet@baylibre.com> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-9-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 139 ++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index e37c9185e4ec..11a94927c0d0 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -35,6 +35,7 @@ #define MTK_DP_SIP_CONTROL_AARCH32 MTK_SIP_SMC_CMD(0x523) #define MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE (BIT(0) | BIT(5)) +#define MTK_DP_SIP_ATF_VIDEO_UNMUTE BIT(5) #define MTK_DP_THREAD_CABLE_STATE_CHG BIT(0) #define MTK_DP_THREAD_HPD_EVENT BIT(1) @@ -199,6 +200,89 @@ static const struct mtk_dp_efuse_fmt mt8195_edp_efuse_fmt[MTK_DP_CAL_MAX] = { }, }; +static const struct mtk_dp_efuse_fmt mt8195_dp_efuse_fmt[MTK_DP_CAL_MAX] = { + [MTK_DP_CAL_GLB_BIAS_TRIM] = { + .idx = 0, + .shift = 27, + .mask = 0x1f, + .min_val = 1, + .max_val = 0x1e, + .default_val = 0xf, + }, + [MTK_DP_CAL_CLKTX_IMPSE] = { + .idx = 0, + .shift = 13, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_0] = { + .idx = 1, + .shift = 28, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_1] = { + .idx = 1, + .shift = 20, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_2] = { + .idx = 1, + .shift = 12, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_PMOS_3] = { + .idx = 1, + .shift = 4, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_0] = { + .idx = 1, + .shift = 24, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_1] = { + .idx = 1, + .shift = 16, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_2] = { + .idx = 1, + .shift = 8, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, + [MTK_DP_CAL_LN_TX_IMPSEL_NMOS_3] = { + .idx = 1, + .shift = 0, + .mask = 0xf, + .min_val = 1, + .max_val = 0xe, + .default_val = 0x8, + }, +}; + static struct regmap_config mtk_dp_regmap_config = { .reg_bits = 32, .val_bits = 32, @@ -1479,6 +1563,50 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, return 0; } +static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) +{ + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + enum drm_connector_status ret = connector_status_disconnected; + bool enabled = mtk_dp->enabled; + u8 sink_count = 0; + + if (mtk_dp->train_info.cable_plugged_in) { + if (!enabled) { + /* power on aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL_LANE, + DP_PWR_STATE_MASK); + + /* power on panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + usleep_range(2000, 5000); + } + /* + * Some dongles still source HPD when they do not connect to any + * sink device. To avoid this, we need to read the sink count + * to make sure we do connect to sink devices. After this detect + * function, we just need to check the HPD connection to check + * whether we connect to a sink device. + */ + drm_dp_dpcd_readb(&mtk_dp->aux, DP_SINK_COUNT, &sink_count); + if (DP_GET_SINK_COUNT(sink_count)) + ret = connector_status_connected; + + if (!enabled) { + /* power off panel */ + drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); + usleep_range(2000, 3000); + + /* power off aux */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP_TPLL, + DP_PWR_STATE_MASK); + } + } + + return ret; +} + static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge, struct drm_connector *connector) { @@ -1865,6 +1993,7 @@ static const struct drm_bridge_funcs mtk_dp_bridge_funcs = { .atomic_disable = mtk_dp_bridge_atomic_disable, .mode_valid = mtk_dp_bridge_mode_valid, .get_edid = mtk_dp_get_edid, + .detect = mtk_dp_bdg_detect, }; static int mtk_dp_probe(struct platform_device *pdev) @@ -1991,11 +2120,21 @@ static const struct mtk_dp_data mt8195_edp_data = { .efuse_fmt = mt8195_edp_efuse_fmt, }; +static const struct mtk_dp_data mt8195_dp_data = { + .bridge_type = DRM_MODE_CONNECTOR_DisplayPort, + .smc_cmd = MTK_DP_SIP_ATF_VIDEO_UNMUTE, + .efuse_fmt = mt8195_dp_efuse_fmt, +}; + static const struct of_device_id mtk_dp_of_match[] = { { .compatible = "mediatek,mt8195-edp-tx", .data = &mt8195_edp_data, }, + { + .compatible = "mediatek,mt8195-dp-tx", + .data = &mt8195_dp_data, + }, {}, }; MODULE_DEVICE_TABLE(of, mtk_dp_of_match); From 4652e95e7ea609426f9196b328abedd564be7275 Mon Sep 17 00:00:00 2001 From: Jitao Shi <jitao.shi@mediatek.com> Date: Thu, 1 Sep 2022 12:41:48 +0800 Subject: [PATCH 358/396] drm/mediatek: dp: Add hpd debounce From the DP spec 1.4a chapter 3.3, upstream devices should implement HPD signal de-bouncing on an external connection. A period of 100ms should be used to detect an HPD connect event. To cover these cases, HPD de-bounce should be implemented only after HPD low has been detected for at least 100ms. Therefore, 1. If HPD is low (which means plugging out) for longer than 100ms: we need to do de-bouncing (which means we need to wait for 100ms). 2. If HPD low is for less than 100ms: we don't need to care about the de-bouncing. In this patch, we start a 100ms timer and use a need_debounce boolean to implement the feature. Two cases when HPD is high: 1. If the timer is expired (>100ms): - need_debounce is true. - When HPD high (plugging event comes), need_debounce will be true and then we need to do de-bouncing (wait for 100ms). 2. If the timer is not expired (<100ms): - need_debounce is false. - When HPD high (plugging event comes), need_debounce will be false and no need to do de-bouncing. HPD_______ __________________ | |<- 100ms -> |____________| <- 100ms -> Without HPD de-bouncing, USB-C to HDMI Adapaters will not be detected. The change has been successfully tested with the following devices: - Dell Adapter - USB-C to HDMI - Acer 1in1 HDMI dongle - Ugreen 1in1 HDMI dongle - innowatt HDMI + USB3 hub - Acer 2in1 HDMI dongle - Apple 3in1 HDMI dongle (A2119) - J5Create 3in1 HDMI dongle (JAC379) Tested-by: Rex-BC Chen <rex-bc.chen@mediatek.com> Reviewed-by: Rex-BC Chen <rex-bc.chen@mediatek.com> Signed-off-by: Jitao Shi <jitao.shi@mediatek.com> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-10-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 11a94927c0d0..dd34dae417e5 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -87,6 +87,7 @@ struct mtk_dp_efuse_fmt { struct mtk_dp { bool enabled; + bool need_debounce; u8 max_lanes; u8 max_linkrate; u8 rx_cap[DP_RECEIVER_CAP_SIZE]; @@ -109,6 +110,7 @@ struct mtk_dp { struct platform_device *phy_dev; struct phy *phy; struct regmap *regs; + struct timer_list debounce_timer; }; struct mtk_dp_data { @@ -1475,14 +1477,24 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev) unsigned long flags; u32 status; + if (mtk_dp->need_debounce && mtk_dp->train_info.cable_plugged_in) + msleep(100); + spin_lock_irqsave(&mtk_dp->irq_thread_lock, flags); status = mtk_dp->irq_thread_handle; mtk_dp->irq_thread_handle = 0; spin_unlock_irqrestore(&mtk_dp->irq_thread_lock, flags); - if (status & MTK_DP_THREAD_CABLE_STATE_CHG) + if (status & MTK_DP_THREAD_CABLE_STATE_CHG) { drm_helper_hpd_irq_event(mtk_dp->bridge.dev); + if (!mtk_dp->train_info.cable_plugged_in) { + mtk_dp->need_debounce = false; + mod_timer(&mtk_dp->debounce_timer, + jiffies + msecs_to_jiffies(100) - 1); + } + } + if (status & MTK_DP_THREAD_HPD_EVENT) dev_dbg(mtk_dp->dev, "Receive IRQ from sink devices\n"); @@ -1996,6 +2008,13 @@ static const struct drm_bridge_funcs mtk_dp_bridge_funcs = { .detect = mtk_dp_bdg_detect, }; +static void mtk_dp_debounce_timer(struct timer_list *t) +{ + struct mtk_dp *mtk_dp = from_timer(mtk_dp, t, debounce_timer); + + mtk_dp->need_debounce = true; +} + static int mtk_dp_probe(struct platform_device *pdev) { struct mtk_dp *mtk_dp; @@ -2069,6 +2088,9 @@ static int mtk_dp_probe(struct platform_device *pdev) drm_bridge_add(&mtk_dp->bridge); + mtk_dp->need_debounce = true; + timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0); + pm_runtime_enable(dev); pm_runtime_get_sync(dev); @@ -2081,6 +2103,7 @@ static int mtk_dp_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); + del_timer_sync(&mtk_dp->debounce_timer); drm_bridge_remove(&mtk_dp->bridge); platform_device_unregister(mtk_dp->phy_dev); From e71a8ebbe086c3d80189726ef46bcf718cbe194d Mon Sep 17 00:00:00 2001 From: Guillaume Ranquet <granquet@baylibre.com> Date: Thu, 1 Sep 2022 12:41:49 +0800 Subject: [PATCH 359/396] drm/mediatek: dp: Audio support for MT8195 This patch adds audio support to the DP driver for MT8195 with up to 8 channels. Signed-off-by: Guillaume Ranquet <granquet@baylibre.com> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-11-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dp.c | 482 +++++++++++++++++++++++++- drivers/gpu/drm/mediatek/mtk_dp_reg.h | 51 +++ 2 files changed, 532 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index dd34dae417e5..dfa942ca62da 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -29,6 +29,7 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/soc/mediatek/mtk_sip_svc.h> +#include <sound/hdmi-codec.h> #include <video/videomode.h> #include "mtk_dp_reg.h" @@ -47,6 +48,8 @@ #define MTK_DP_TBC_BUF_READ_START_ADDR 0x8 #define MTK_DP_TRAIN_VOLTAGE_LEVEL_RETRY 5 #define MTK_DP_TRAIN_DOWNSCALE_RETRY 10 +#define MTK_DP_VERSION 0x11 +#define MTK_DP_SDP_AUI 0x4 enum { MTK_DP_CAL_GLB_BIAS_TRIM = 0, @@ -71,9 +74,18 @@ struct mtk_dp_train_info { unsigned int channel_eq_pattern; }; +struct mtk_dp_audio_cfg { + bool detect_monitor; + int sad_count; + int sample_rate; + int word_length_bits; + int channels; +}; + struct mtk_dp_info { enum dp_pixelformat format; struct videomode vm; + struct mtk_dp_audio_cfg audio_cur_cfg; }; struct mtk_dp_efuse_fmt { @@ -111,12 +123,22 @@ struct mtk_dp { struct phy *phy; struct regmap *regs; struct timer_list debounce_timer; + + /* For audio */ + bool audio_enable; + hdmi_codec_plugged_cb plugged_cb; + struct platform_device *audio_pdev; + + struct device *codec_dev; + /* protect the plugged_cb as it's used in both bridge ops and audio */ + struct mutex update_plugged_status_lock; }; struct mtk_dp_data { int bridge_type; unsigned int smc_cmd; const struct mtk_dp_efuse_fmt *efuse_fmt; + bool audio_supported; }; static const struct mtk_dp_efuse_fmt mt8195_edp_efuse_fmt[MTK_DP_CAL_MAX] = { @@ -512,6 +534,169 @@ static void mtk_dp_pg_enable(struct mtk_dp *mtk_dp, bool enable) PGEN_PATTERN_SEL_VAL << 4, PGEN_PATTERN_SEL_MASK); } +static void mtk_dp_audio_setup_channels(struct mtk_dp *mtk_dp, + struct mtk_dp_audio_cfg *cfg) +{ + u32 channel_enable_bits; + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3324, + AUDIO_SOURCE_MUX_DP_ENC1_P0_DPRX, + AUDIO_SOURCE_MUX_DP_ENC1_P0_MASK); + + /* audio channel count change reset */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_33F4, + DP_ENC_DUMMY_RW_1, DP_ENC_DUMMY_RW_1); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3304, + AU_PRTY_REGEN_DP_ENC1_P0_MASK | + AU_CH_STS_REGEN_DP_ENC1_P0_MASK | + AUDIO_SAMPLE_PRSENT_REGEN_DP_ENC1_P0_MASK, + AU_PRTY_REGEN_DP_ENC1_P0_MASK | + AU_CH_STS_REGEN_DP_ENC1_P0_MASK | + AUDIO_SAMPLE_PRSENT_REGEN_DP_ENC1_P0_MASK); + + switch (cfg->channels) { + case 2: + channel_enable_bits = AUDIO_2CH_SEL_DP_ENC0_P0_MASK | + AUDIO_2CH_EN_DP_ENC0_P0_MASK; + break; + case 8: + default: + channel_enable_bits = AUDIO_8CH_SEL_DP_ENC0_P0_MASK | + AUDIO_8CH_EN_DP_ENC0_P0_MASK; + break; + } + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3088, + channel_enable_bits | AU_EN_DP_ENC0_P0, + AUDIO_2CH_SEL_DP_ENC0_P0_MASK | + AUDIO_2CH_EN_DP_ENC0_P0_MASK | + AUDIO_8CH_SEL_DP_ENC0_P0_MASK | + AUDIO_8CH_EN_DP_ENC0_P0_MASK | + AU_EN_DP_ENC0_P0); + + /* audio channel count change reset */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_33F4, 0, DP_ENC_DUMMY_RW_1); + + /* enable audio reset */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_33F4, + DP_ENC_DUMMY_RW_1_AUDIO_RST_EN, + DP_ENC_DUMMY_RW_1_AUDIO_RST_EN); +} + +static void mtk_dp_audio_channel_status_set(struct mtk_dp *mtk_dp, + struct mtk_dp_audio_cfg *cfg) +{ + struct snd_aes_iec958 iec = { 0 }; + + switch (cfg->sample_rate) { + case 32000: + iec.status[3] = IEC958_AES3_CON_FS_32000; + break; + case 44100: + iec.status[3] = IEC958_AES3_CON_FS_44100; + break; + case 48000: + iec.status[3] = IEC958_AES3_CON_FS_48000; + break; + case 88200: + iec.status[3] = IEC958_AES3_CON_FS_88200; + break; + case 96000: + iec.status[3] = IEC958_AES3_CON_FS_96000; + break; + case 192000: + iec.status[3] = IEC958_AES3_CON_FS_192000; + break; + default: + iec.status[3] = IEC958_AES3_CON_FS_NOTID; + break; + } + + switch (cfg->word_length_bits) { + case 16: + iec.status[4] = IEC958_AES4_CON_WORDLEN_20_16; + break; + case 20: + iec.status[4] = IEC958_AES4_CON_WORDLEN_20_16 | + IEC958_AES4_CON_MAX_WORDLEN_24; + break; + case 24: + iec.status[4] = IEC958_AES4_CON_WORDLEN_24_20 | + IEC958_AES4_CON_MAX_WORDLEN_24; + break; + default: + iec.status[4] = IEC958_AES4_CON_WORDLEN_NOTID; + } + + /* IEC 60958 consumer channel status bits */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_308C, + 0, CH_STATUS_0_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3090, + iec.status[3] << 8, CH_STATUS_1_DP_ENC0_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3094, + iec.status[4], CH_STATUS_2_DP_ENC0_P0_MASK); +} + +static void mtk_dp_audio_sdp_asp_set_channels(struct mtk_dp *mtk_dp, + int channels) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_312C, + (min(8, channels) - 1) << 8, + ASP_HB2_DP_ENC0_P0_MASK | ASP_HB3_DP_ENC0_P0_MASK); +} + +static void mtk_dp_audio_set_divider(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_30BC, + AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_DIV_2, + AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_MASK); +} + +static void mtk_dp_sdp_trigger_aui(struct mtk_dp *mtk_dp) +{ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3280, + MTK_DP_SDP_AUI, SDP_PACKET_TYPE_DP_ENC1_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3280, + SDP_PACKET_W_DP_ENC1_P0, SDP_PACKET_W_DP_ENC1_P0); +} + +static void mtk_dp_sdp_set_data(struct mtk_dp *mtk_dp, u8 *data_bytes) +{ + mtk_dp_bulk_16bit_write(mtk_dp, MTK_DP_ENC1_P0_3200, + data_bytes, 0x10); +} + +static void mtk_dp_sdp_set_header_aui(struct mtk_dp *mtk_dp, + struct dp_sdp_header *header) +{ + u32 db_addr = MTK_DP_ENC0_P0_30D8 + (MTK_DP_SDP_AUI - 1) * 8; + + mtk_dp_bulk_16bit_write(mtk_dp, db_addr, (u8 *)header, 4); +} + +static void mtk_dp_disable_sdp_aui(struct mtk_dp *mtk_dp) +{ + /* Disable periodic send */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_30A8 & 0xfffc, 0, + 0xff << ((MTK_DP_ENC0_P0_30A8 & 3) * 8)); +} + +static void mtk_dp_setup_sdp_aui(struct mtk_dp *mtk_dp, + struct dp_sdp *sdp) +{ + u32 shift; + + mtk_dp_sdp_set_data(mtk_dp, sdp->db); + mtk_dp_sdp_set_header_aui(mtk_dp, &sdp->sdp_header); + mtk_dp_disable_sdp_aui(mtk_dp); + + shift = (MTK_DP_ENC0_P0_30A8 & 3) * 8; + + mtk_dp_sdp_trigger_aui(mtk_dp); + /* Enable periodic sending */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_30A8 & 0xfffc, + 0x05 << shift, 0xff << shift); +} + static void mtk_dp_aux_irq_clear(struct mtk_dp *mtk_dp) { mtk_dp_write(mtk_dp, MTK_DP_AUX_P0_3640, DP_AUX_P0_3640_VAL); @@ -1041,6 +1226,32 @@ static void mtk_dp_video_mute(struct mtk_dp *mtk_dp, bool enable) mtk_dp->data->smc_cmd, enable, res.a0, res.a1); } +static void mtk_dp_audio_mute(struct mtk_dp *mtk_dp, bool mute) +{ + u32 val[3]; + + if (mute) { + val[0] = VBID_AUDIO_MUTE_FLAG_SW_DP_ENC0_P0 | + VBID_AUDIO_MUTE_FLAG_SEL_DP_ENC0_P0; + val[1] = 0; + val[2] = 0; + } else { + val[0] = 0; + val[1] = AU_EN_DP_ENC0_P0; + /* Send one every two frames */ + val[2] = 0x0F; + } + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3030, + val[0], + VBID_AUDIO_MUTE_FLAG_SW_DP_ENC0_P0 | + VBID_AUDIO_MUTE_FLAG_SEL_DP_ENC0_P0); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3088, + val[1], AU_EN_DP_ENC0_P0); + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_30A4, + val[2], AU_TS_CFG_DP_ENC0_P0_MASK); +} + static void mtk_dp_power_enable(struct mtk_dp *mtk_dp) { mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_RESET_AND_PROBE, @@ -1080,6 +1291,76 @@ static void mtk_dp_initialize_priv_data(struct mtk_dp *mtk_dp) mtk_dp->info.format = DP_PIXELFORMAT_RGB; memset(&mtk_dp->info.vm, 0, sizeof(struct videomode)); + mtk_dp->audio_enable = false; +} + +static void mtk_dp_sdp_set_down_cnt_init(struct mtk_dp *mtk_dp, + u32 sram_read_start) +{ + u32 sdp_down_cnt_init = 0; + struct drm_display_mode mode; + struct videomode *vm = &mtk_dp->info.vm; + + drm_display_mode_from_videomode(vm, &mode); + + if (mode.clock > 0) + sdp_down_cnt_init = sram_read_start * + mtk_dp->train_info.link_rate * 2700 * 8 / + (mode.clock * 4); + + switch (mtk_dp->train_info.lane_count) { + case 1: + sdp_down_cnt_init = max_t(u32, sdp_down_cnt_init, 0x1A); + break; + case 2: + /* case for LowResolution && High Audio Sample Rate */ + sdp_down_cnt_init = max_t(u32, sdp_down_cnt_init, 0x10); + sdp_down_cnt_init += mode.vtotal <= 525 ? 4 : 0; + break; + case 4: + default: + sdp_down_cnt_init = max_t(u32, sdp_down_cnt_init, 6); + break; + } + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3040, + sdp_down_cnt_init, + SDP_DOWN_CNT_INIT_DP_ENC0_P0_MASK); +} + +static void mtk_dp_sdp_set_down_cnt_init_in_hblank(struct mtk_dp *mtk_dp) +{ + int pix_clk_mhz; + u32 dc_offset; + u32 spd_down_cnt_init = 0; + struct drm_display_mode mode; + struct videomode *vm = &mtk_dp->info.vm; + + drm_display_mode_from_videomode(vm, &mode); + + pix_clk_mhz = mtk_dp->info.format == DP_PIXELFORMAT_YUV420 ? + mode.clock / 2000 : mode.clock / 1000; + + switch (mtk_dp->train_info.lane_count) { + case 1: + spd_down_cnt_init = 0x20; + break; + case 2: + dc_offset = (mode.vtotal <= 525) ? 0x14 : 0x00; + spd_down_cnt_init = 0x18 + dc_offset; + break; + case 4: + default: + dc_offset = (mode.vtotal <= 525) ? 0x08 : 0x00; + if (pix_clk_mhz > mtk_dp->train_info.link_rate * 27) + spd_down_cnt_init = 0x8; + else + spd_down_cnt_init = 0x10 + dc_offset; + break; + } + + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3364, spd_down_cnt_init, + SDP_DOWN_CNT_INIT_IN_HBLANK_DP_ENC1_P0_MASK); } static void mtk_dp_setup_tu(struct mtk_dp *mtk_dp) @@ -1091,6 +1372,8 @@ static void mtk_dp_setup_tu(struct mtk_dp *mtk_dp) MTK_DP_PIX_PER_ADDR); mtk_dp_set_sram_read_start(mtk_dp, sram_read_start); mtk_dp_setup_encoder(mtk_dp); + mtk_dp_sdp_set_down_cnt_init_in_hblank(mtk_dp); + mtk_dp_sdp_set_down_cnt_init(mtk_dp, sram_read_start); } static void mtk_dp_set_tx_out(struct mtk_dp *mtk_dp) @@ -1342,6 +1625,20 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp) return 0; } +static bool mtk_dp_edid_parse_audio_capabilities(struct mtk_dp *mtk_dp, + struct mtk_dp_audio_cfg *cfg) +{ + if (!mtk_dp->data->audio_supported) + return false; + + if (mtk_dp->info.audio_cur_cfg.sad_count <= 0) { + drm_info(mtk_dp->drm_dev, "The SADs is NULL\n"); + return false; + } + + return true; +} + static void mtk_dp_train_change_mode(struct mtk_dp *mtk_dp) { phy_reset(mtk_dp->phy); @@ -1446,6 +1743,46 @@ static void mtk_dp_video_enable(struct mtk_dp *mtk_dp, bool enable) } } +static void mtk_dp_audio_sdp_setup(struct mtk_dp *mtk_dp, + struct mtk_dp_audio_cfg *cfg) +{ + struct dp_sdp sdp; + struct hdmi_audio_infoframe frame; + + hdmi_audio_infoframe_init(&frame); + frame.coding_type = HDMI_AUDIO_CODING_TYPE_PCM; + frame.channels = cfg->channels; + frame.sample_frequency = cfg->sample_rate; + + switch (cfg->word_length_bits) { + case 16: + frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_16; + break; + case 20: + frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_20; + break; + case 24: + default: + frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_24; + break; + } + + hdmi_audio_infoframe_pack_for_dp(&frame, &sdp, MTK_DP_VERSION); + + mtk_dp_audio_sdp_asp_set_channels(mtk_dp, cfg->channels); + mtk_dp_setup_sdp_aui(mtk_dp, &sdp); +} + +static void mtk_dp_audio_setup(struct mtk_dp *mtk_dp, + struct mtk_dp_audio_cfg *cfg) +{ + mtk_dp_audio_sdp_setup(mtk_dp, cfg); + mtk_dp_audio_channel_status_set(mtk_dp, cfg); + + mtk_dp_audio_setup_channels(mtk_dp, cfg); + mtk_dp_audio_set_divider(mtk_dp); +} + static int mtk_dp_video_config(struct mtk_dp *mtk_dp) { mtk_dp_config_mn_mode(mtk_dp); @@ -1489,6 +1826,10 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev) drm_helper_hpd_irq_event(mtk_dp->bridge.dev); if (!mtk_dp->train_info.cable_plugged_in) { + mtk_dp_disable_sdp_aui(mtk_dp); + memset(&mtk_dp->info.audio_cur_cfg, 0, + sizeof(mtk_dp->info.audio_cur_cfg)); + mtk_dp->need_debounce = false; mod_timer(&mtk_dp->debounce_timer, jiffies + msecs_to_jiffies(100) - 1); @@ -1575,6 +1916,16 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, return 0; } +static void mtk_dp_update_plugged_status(struct mtk_dp *mtk_dp) +{ + mutex_lock(&mtk_dp->update_plugged_status_lock); + if (mtk_dp->plugged_cb && mtk_dp->codec_dev) + mtk_dp->plugged_cb(mtk_dp->codec_dev, + mtk_dp->enabled & + mtk_dp->info.audio_cur_cfg.detect_monitor); + mutex_unlock(&mtk_dp->update_plugged_status_lock); +} + static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) { struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); @@ -1615,7 +1966,6 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) DP_PWR_STATE_MASK); } } - return ret; } @@ -1625,6 +1975,8 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge, struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); bool enabled = mtk_dp->enabled; struct edid *new_edid = NULL; + struct mtk_dp_audio_cfg *audio_caps = &mtk_dp->info.audio_cur_cfg; + struct cea_sad *sads; if (!enabled) { drm_bridge_chain_pre_enable(bridge); @@ -1650,6 +2002,11 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge, new_edid = NULL; } + if (new_edid) { + audio_caps->sad_count = drm_edid_to_sad(new_edid, &sads); + audio_caps->detect_monitor = drm_detect_monitor_audio(new_edid); + } + if (!enabled) { /* power off panel */ drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); @@ -1843,7 +2200,19 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge, mtk_dp_video_enable(mtk_dp, true); + mtk_dp->audio_enable = + mtk_dp_edid_parse_audio_capabilities(mtk_dp, + &mtk_dp->info.audio_cur_cfg); + if (mtk_dp->audio_enable) { + mtk_dp_audio_setup(mtk_dp, &mtk_dp->info.audio_cur_cfg); + mtk_dp_audio_mute(mtk_dp, false); + } else { + memset(&mtk_dp->info.audio_cur_cfg, 0, + sizeof(mtk_dp->info.audio_cur_cfg)); + } + mtk_dp->enabled = true; + mtk_dp_update_plugged_status(mtk_dp); return; power_off_aux: @@ -1858,7 +2227,9 @@ static void mtk_dp_bridge_atomic_disable(struct drm_bridge *bridge, struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); mtk_dp->enabled = false; + mtk_dp_update_plugged_status(mtk_dp); mtk_dp_video_enable(mtk_dp, false); + mtk_dp_audio_mute(mtk_dp, true); if (mtk_dp->train_info.cable_plugged_in) { drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3); @@ -2015,6 +2386,100 @@ static void mtk_dp_debounce_timer(struct timer_list *t) mtk_dp->need_debounce = true; } +/* + * HDMI audio codec callbacks + */ +static int mtk_dp_audio_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) +{ + struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + + if (!mtk_dp->enabled) { + dev_err(mtk_dp->dev, "%s, DP is not ready!\n", __func__); + return -ENODEV; + } + + mtk_dp->info.audio_cur_cfg.channels = params->cea.channels; + mtk_dp->info.audio_cur_cfg.sample_rate = params->sample_rate; + + mtk_dp_audio_setup(mtk_dp, &mtk_dp->info.audio_cur_cfg); + + return 0; +} + +static int mtk_dp_audio_startup(struct device *dev, void *data) +{ + struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + + mtk_dp_audio_mute(mtk_dp, false); + + return 0; +} + +static void mtk_dp_audio_shutdown(struct device *dev, void *data) +{ + struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + + mtk_dp_audio_mute(mtk_dp, true); +} + +static int mtk_dp_audio_get_eld(struct device *dev, void *data, uint8_t *buf, + size_t len) +{ + struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + + if (mtk_dp->enabled) + memcpy(buf, mtk_dp->conn->eld, len); + else + memset(buf, 0, len); + + return 0; +} + +static int mtk_dp_audio_hook_plugged_cb(struct device *dev, void *data, + hdmi_codec_plugged_cb fn, + struct device *codec_dev) +{ + struct mtk_dp *mtk_dp = data; + + mutex_lock(&mtk_dp->update_plugged_status_lock); + mtk_dp->plugged_cb = fn; + mtk_dp->codec_dev = codec_dev; + mutex_unlock(&mtk_dp->update_plugged_status_lock); + + mtk_dp_update_plugged_status(mtk_dp); + + return 0; +} + +static const struct hdmi_codec_ops mtk_dp_audio_codec_ops = { + .hw_params = mtk_dp_audio_hw_params, + .audio_startup = mtk_dp_audio_startup, + .audio_shutdown = mtk_dp_audio_shutdown, + .get_eld = mtk_dp_audio_get_eld, + .hook_plugged_cb = mtk_dp_audio_hook_plugged_cb, + .no_capture_mute = 1, +}; + +static int mtk_dp_register_audio_driver(struct device *dev) +{ + struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + struct hdmi_codec_pdata codec_data = { + .ops = &mtk_dp_audio_codec_ops, + .max_i2s_channels = 8, + .i2s = 1, + .data = mtk_dp, + }; + + mtk_dp->audio_pdev = platform_device_register_data(dev, + HDMI_CODEC_DRV_NAME, + PLATFORM_DEVID_AUTO, + &codec_data, + sizeof(codec_data)); + return PTR_ERR_OR_ZERO(mtk_dp->audio_pdev); +} + static int mtk_dp_probe(struct platform_device *pdev) { struct mtk_dp *mtk_dp; @@ -2059,8 +2524,19 @@ static int mtk_dp_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "failed to request mediatek dptx irq\n"); + mutex_init(&mtk_dp->update_plugged_status_lock); + platform_set_drvdata(pdev, mtk_dp); + if (mtk_dp->data->audio_supported) { + ret = mtk_dp_register_audio_driver(dev); + if (ret) { + dev_err(dev, "Failed to register audio driver: %d\n", + ret); + return ret; + } + } + mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy", PLATFORM_DEVID_AUTO, &mtk_dp->regs, @@ -2106,6 +2582,8 @@ static int mtk_dp_remove(struct platform_device *pdev) del_timer_sync(&mtk_dp->debounce_timer); drm_bridge_remove(&mtk_dp->bridge); platform_device_unregister(mtk_dp->phy_dev); + if (mtk_dp->audio_pdev) + platform_device_unregister(mtk_dp->audio_pdev); return 0; } @@ -2141,12 +2619,14 @@ static const struct mtk_dp_data mt8195_edp_data = { .bridge_type = DRM_MODE_CONNECTOR_eDP, .smc_cmd = MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, .efuse_fmt = mt8195_edp_efuse_fmt, + .audio_supported = false, }; static const struct mtk_dp_data mt8195_dp_data = { .bridge_type = DRM_MODE_CONNECTOR_DisplayPort, .smc_cmd = MTK_DP_SIP_ATF_VIDEO_UNMUTE, .efuse_fmt = mt8195_dp_efuse_fmt, + .audio_supported = true, }; static const struct of_device_id mtk_dp_of_match[] = { diff --git a/drivers/gpu/drm/mediatek/mtk_dp_reg.h b/drivers/gpu/drm/mediatek/mtk_dp_reg.h index 3f01ba44871f..096ad6572a5e 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp_reg.h +++ b/drivers/gpu/drm/mediatek/mtk_dp_reg.h @@ -115,6 +115,8 @@ #define HSW_SEL_DP_ENC0_P0 BIT(7) #define VSP_SEL_DP_ENC0_P0 BIT(8) #define VSW_SEL_DP_ENC0_P0 BIT(9) +#define VBID_AUDIO_MUTE_FLAG_SW_DP_ENC0_P0 BIT(11) +#define VBID_AUDIO_MUTE_FLAG_SEL_DP_ENC0_P0 BIT(12) #define MTK_DP_ENC0_P0_3034 0x3034 #define MTK_DP_ENC0_P0_3038 0x3038 #define VIDEO_SOURCE_SEL_DP_ENC0_P0_MASK BIT(11) @@ -139,6 +141,38 @@ #define SDP_VSYNC_RISING_MASK_DP_ENC0_P0_MASK BIT(8) #define MTK_DP_ENC0_P0_3064 0x3064 #define HDE_NUM_LAST_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3088 0x3088 +#define AU_EN_DP_ENC0_P0 BIT(6) +#define AUDIO_8CH_EN_DP_ENC0_P0_MASK BIT(7) +#define AUDIO_8CH_SEL_DP_ENC0_P0_MASK BIT(8) +#define AUDIO_2CH_EN_DP_ENC0_P0_MASK BIT(14) +#define AUDIO_2CH_SEL_DP_ENC0_P0_MASK BIT(15) +#define MTK_DP_ENC0_P0_308C 0x308c +#define CH_STATUS_0_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3090 0x3090 +#define CH_STATUS_1_DP_ENC0_P0_MASK GENMASK(15, 0) +#define MTK_DP_ENC0_P0_3094 0x3094 +#define CH_STATUS_2_DP_ENC0_P0_MASK GENMASK(7, 0) +#define MTK_DP_ENC0_P0_30A0 0x30a0 +#define DP_ENC0_30A0_MASK (BIT(7) | BIT(8) | BIT(12)) +#define MTK_DP_ENC0_P0_30A4 0x30a4 +#define AU_TS_CFG_DP_ENC0_P0_MASK GENMASK(7, 0) +#define MTK_DP_ENC0_P0_30A8 0x30a8 +#define MTK_DP_ENC0_P0_30BC 0x30bc +#define ISRC_CONT_DP_ENC0_P0 BIT(0) +#define AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_MASK GENMASK(10, 8) +#define AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_MUL_2 (1 << 8) +#define AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_MUL_4 (2 << 8) +#define AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_MUL_8 (3 << 8) +#define AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_DIV_2 (5 << 8) +#define AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_DIV_4 (6 << 8) +#define AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_DIV_8 (7 << 8) +#define MTK_DP_ENC0_P0_30D8 0x30d8 +#define MTK_DP_ENC0_P0_312C 0x312c +#define ASP_HB2_DP_ENC0_P0_MASK GENMASK(7, 0) +#define ASP_HB3_DP_ENC0_P0_MASK GENMASK(15, 8) +#define MTK_DP_ENC0_P0_3130 0x3130 +#define MTK_DP_ENC0_P0_3138 0x3138 #define MTK_DP_ENC0_P0_3154 0x3154 #define PGEN_HTOTAL_DP_ENC0_P0_MASK GENMASK(13, 0) #define MTK_DP_ENC0_P0_3158 0x3158 @@ -167,9 +201,23 @@ #define ISRC1_HB3_DP_ENC0_P0_MASK GENMASK(15, 8) /* offset: ENC1_OFFSET (0x3200) */ +#define MTK_DP_ENC1_P0_3200 0x3200 +#define MTK_DP_ENC1_P0_3280 0x3280 +#define SDP_PACKET_TYPE_DP_ENC1_P0_MASK GENMASK(4, 0) +#define SDP_PACKET_W_DP_ENC1_P0 BIT(5) +#define SDP_PACKET_W_DP_ENC1_P0_MASK BIT(5) +#define MTK_DP_ENC1_P0_328C 0x328c +#define VSC_DATA_RDY_VESA_DP_ENC1_P0_MASK BIT(7) #define MTK_DP_ENC1_P0_3300 0x3300 #define VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_VAL 2 #define VIDEO_AFIFO_RDY_SEL_DP_ENC1_P0_MASK GENMASK(9, 8) +#define MTK_DP_ENC1_P0_3304 0x3304 +#define AU_PRTY_REGEN_DP_ENC1_P0_MASK BIT(8) +#define AU_CH_STS_REGEN_DP_ENC1_P0_MASK BIT(9) +#define AUDIO_SAMPLE_PRSENT_REGEN_DP_ENC1_P0_MASK BIT(12) +#define MTK_DP_ENC1_P0_3324 0x3324 +#define AUDIO_SOURCE_MUX_DP_ENC1_P0_MASK GENMASK(9, 8) +#define AUDIO_SOURCE_MUX_DP_ENC1_P0_DPRX 0 #define MTK_DP_ENC1_P0_3364 0x3364 #define SDP_DOWN_CNT_IN_HBLANK_DP_ENC1_P0_VAL 0x20 #define SDP_DOWN_CNT_INIT_IN_HBLANK_DP_ENC1_P0_MASK GENMASK(11, 0) @@ -186,6 +234,9 @@ VIDEO_STABLE_CNT_THRD_DP_ENC1_P0 | \ SDP_DP13_EN_DP_ENC1_P0 | \ BS2BS_MODE_DP_ENC1_P0) +#define MTK_DP_ENC1_P0_33F4 0x33f4 +#define DP_ENC_DUMMY_RW_1_AUDIO_RST_EN BIT(0) +#define DP_ENC_DUMMY_RW_1 BIT(9) /* offset: TRANS_OFFSET (0x3400) */ #define MTK_DP_TRANS_P0_3400 0x3400 From 981f09295687f856d5345e19c7084aca481c1395 Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Mon, 1 Aug 2022 13:38:02 +0000 Subject: [PATCH 360/396] drm: hide unregistered connectors from GETCONNECTOR IOCTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When registering a connector, the kernel sends a hotplug uevent in drm_connector_register(). When unregistering a connector, drivers are expected to send a uevent as well. However, user-space has no way to figure out that the connector isn't registered anymore: it'll still be reported in GETCONNECTOR IOCTLs. The documentation for DRM_CONNECTOR_UNREGISTERED states: > The connector […] has since been unregistered and removed from > userspace, or the connector was unregistered before it had a chance > to be exposed to userspace Signed-off-by: Simon Ser <contact@emersion.fr> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220801133754.461037-1-contact@emersion.fr --- drivers/gpu/drm/drm_mode_config.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 688c8afe0bf1..939d621c9ad4 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -151,6 +151,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data, count = 0; connector_id = u64_to_user_ptr(card_res->connector_id_ptr); drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->registration_state != DRM_CONNECTOR_REGISTERED) + continue; + /* only expose writeback connectors if userspace understands them */ if (!file_priv->writeback_connectors && (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)) From 0aedc880025ffed5be6736bca61ace31f591b92d Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Mon, 29 Aug 2022 15:14:56 +0000 Subject: [PATCH 361/396] drm/atomic-helper: print message on driver connector check failure Sometimes drivers are missing logs when they return EINVAL. Printing the failure here in common code can help understand where EINVAL is coming from. All other atomic_check() calls in this file already have similar logging. v2: add missing newlines Signed-off-by: Simon Ser <contact@emersion.fr> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220829151451.152114-1-contact@emersion.fr --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index c6abfd3d4b62..4aa05b626b57 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -702,8 +702,12 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, if (funcs->atomic_check) ret = funcs->atomic_check(connector, state); - if (ret) + if (ret) { + drm_dbg_atomic(dev, + "[CONNECTOR:%d:%s] driver check failed\n", + connector->base.id, connector->name); return ret; + } connectors_mask |= BIT(i); } @@ -745,8 +749,12 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, if (funcs->atomic_check) ret = funcs->atomic_check(connector, state); - if (ret) + if (ret) { + drm_dbg_atomic(dev, + "[CONNECTOR:%d:%s] driver check failed\n", + connector->base.id, connector->name); return ret; + } } /* From 8fe444eb326869823f3788a4b4da5dca03339d10 Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Mon, 29 Aug 2022 15:15:03 +0000 Subject: [PATCH 362/396] drm/atomic-helper: log EINVAL cause in drm_atomic_helper_async_check() This can help figure out why the kernel returns EINVAL from user-space. v2: add missing newlines Signed-off-by: Simon Ser <contact@emersion.fr> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220829151451.152114-2-contact@emersion.fr --- drivers/gpu/drm/drm_atomic_helper.c | 32 +++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4aa05b626b57..d36720f419f7 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1796,7 +1796,7 @@ int drm_atomic_helper_async_check(struct drm_device *dev, struct drm_plane_state *old_plane_state = NULL; struct drm_plane_state *new_plane_state = NULL; const struct drm_plane_helper_funcs *funcs; - int i, n_planes = 0; + int i, ret, n_planes = 0; for_each_new_crtc_in_state(state, crtc, crtc_state, i) { if (drm_atomic_crtc_needs_modeset(crtc_state)) @@ -1807,19 +1807,34 @@ int drm_atomic_helper_async_check(struct drm_device *dev, n_planes++; /* FIXME: we support only single plane updates for now */ - if (n_planes != 1) + if (n_planes != 1) { + drm_dbg_atomic(dev, + "only single plane async updates are supported\n"); return -EINVAL; + } if (!new_plane_state->crtc || - old_plane_state->crtc != new_plane_state->crtc) + old_plane_state->crtc != new_plane_state->crtc) { + drm_dbg_atomic(dev, + "[PLANE:%d:%s] async update cannot change CRTC\n", + plane->base.id, plane->name); return -EINVAL; + } funcs = plane->helper_private; - if (!funcs->atomic_async_update) + if (!funcs->atomic_async_update) { + drm_dbg_atomic(dev, + "[PLANE:%d:%s] driver does not support async updates\n", + plane->base.id, plane->name); return -EINVAL; + } - if (new_plane_state->fence) + if (new_plane_state->fence) { + drm_dbg_atomic(dev, + "[PLANE:%d:%s] missing fence for async update\n", + plane->base.id, plane->name); return -EINVAL; + } /* * Don't do an async update if there is an outstanding commit modifying @@ -1834,7 +1849,12 @@ int drm_atomic_helper_async_check(struct drm_device *dev, return -EBUSY; } - return funcs->atomic_async_check(plane, state); + ret = funcs->atomic_async_check(plane, state); + if (ret != 0) + drm_dbg_atomic(dev, + "[PLANE:%d:%s] driver async check failed\n", + plane->base.id, plane->name); + return ret; } EXPORT_SYMBOL(drm_atomic_helper_async_check); From 2a37630d0ddb8a0612b700635cf4827aeafe4142 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:03 -0300 Subject: [PATCH 363/396] drm: vkms: Replace hardcoded value of `vkms_composer.map` to DRM_FORMAT_MAX_PLANES The `map` vector at `vkms_composer` uses a hardcoded value to define its size. If someday the maximum number of planes increases, this hardcoded value can be a problem. This value is being replaced with the DRM_FORMAT_MAX_PLANES macro. Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-2-igormtorrente@gmail.com --- drivers/gpu/drm/vkms/vkms_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 1d60654b553b..ae6c5a3d356c 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -31,7 +31,7 @@ struct vkms_writeback_job { struct vkms_composer { struct drm_framebuffer fb; struct drm_rect src, dst; - struct iosys_map map[4]; + struct iosys_map map[DRM_FORMAT_MAX_PLANES]; unsigned int offset; unsigned int pitch; unsigned int cpp; From 1645e7b9667f14a37f9ac8c49568b8f979227d20 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:04 -0300 Subject: [PATCH 364/396] drm: vkms: Rename `vkms_composer` to `vkms_frame_info` Changes the name of this struct to a more meaningful name. A name that represents better what this struct is about. Composer is the code that do the compositing of the planes. This struct contains information on the frame used in the output composition. Thus, vkms_frame_info is a better name to represent this. V5: Fix a commit message typo(Melissa Wen). V6: Fix wrong iosys_map_is_null verification at compose_plane (Melissa Wen). Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-3-igormtorrente@gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 87 ++++++++++++++-------------- drivers/gpu/drm/vkms/vkms_drv.h | 6 +- drivers/gpu/drm/vkms/vkms_plane.c | 38 ++++++------ 3 files changed, 66 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 775b97766e08..7c62c5741430 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -11,11 +11,11 @@ #include "vkms_drv.h" static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer, - const struct vkms_composer *composer) + const struct vkms_frame_info *frame_info) { u32 pixel; - int src_offset = composer->offset + (y * composer->pitch) - + (x * composer->cpp); + int src_offset = frame_info->offset + (y * frame_info->pitch) + + (x * frame_info->cpp); pixel = *(u32 *)&buffer[src_offset]; @@ -26,24 +26,24 @@ static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer, * compute_crc - Compute CRC value on output frame * * @vaddr: address to final framebuffer - * @composer: framebuffer's metadata + * @frame_info: framebuffer's metadata * * returns CRC value computed using crc32 on the visible portion of * the final framebuffer at vaddr_out */ static uint32_t compute_crc(const u8 *vaddr, - const struct vkms_composer *composer) + const struct vkms_frame_info *frame_info) { int x, y; u32 crc = 0, pixel = 0; - int x_src = composer->src.x1 >> 16; - int y_src = composer->src.y1 >> 16; - int h_src = drm_rect_height(&composer->src) >> 16; - int w_src = drm_rect_width(&composer->src) >> 16; + int x_src = frame_info->src.x1 >> 16; + int y_src = frame_info->src.y1 >> 16; + int h_src = drm_rect_height(&frame_info->src) >> 16; + int w_src = drm_rect_width(&frame_info->src) >> 16; for (y = y_src; y < y_src + h_src; ++y) { for (x = x_src; x < x_src + w_src; ++x) { - pixel = get_pixel_from_buffer(x, y, vaddr, composer); + pixel = get_pixel_from_buffer(x, y, vaddr, frame_info); crc = crc32_le(crc, (void *)&pixel, sizeof(u32)); } } @@ -98,8 +98,8 @@ static void x_blend(const u8 *xrgb_src, u8 *xrgb_dst) * blend - blend value at vaddr_src with value at vaddr_dst * @vaddr_dst: destination address * @vaddr_src: source address - * @dst_composer: destination framebuffer's metadata - * @src_composer: source framebuffer's metadata + * @dst_frame_info: destination framebuffer's metadata + * @src_frame_info: source framebuffer's metadata * @pixel_blend: blending equation based on plane format * * Blend the vaddr_src value with the vaddr_dst value using a pixel blend @@ -111,33 +111,33 @@ static void x_blend(const u8 *xrgb_src, u8 *xrgb_dst) * pixel color values */ static void blend(void *vaddr_dst, void *vaddr_src, - struct vkms_composer *dst_composer, - struct vkms_composer *src_composer, + struct vkms_frame_info *dst_frame_info, + struct vkms_frame_info *src_frame_info, void (*pixel_blend)(const u8 *, u8 *)) { int i, j, j_dst, i_dst; int offset_src, offset_dst; u8 *pixel_dst, *pixel_src; - int x_src = src_composer->src.x1 >> 16; - int y_src = src_composer->src.y1 >> 16; + int x_src = src_frame_info->src.x1 >> 16; + int y_src = src_frame_info->src.y1 >> 16; - int x_dst = src_composer->dst.x1; - int y_dst = src_composer->dst.y1; - int h_dst = drm_rect_height(&src_composer->dst); - int w_dst = drm_rect_width(&src_composer->dst); + int x_dst = src_frame_info->dst.x1; + int y_dst = src_frame_info->dst.y1; + int h_dst = drm_rect_height(&src_frame_info->dst); + int w_dst = drm_rect_width(&src_frame_info->dst); int y_limit = y_src + h_dst; int x_limit = x_src + w_dst; for (i = y_src, i_dst = y_dst; i < y_limit; ++i) { for (j = x_src, j_dst = x_dst; j < x_limit; ++j) { - offset_dst = dst_composer->offset - + (i_dst * dst_composer->pitch) - + (j_dst++ * dst_composer->cpp); - offset_src = src_composer->offset - + (i * src_composer->pitch) - + (j * src_composer->cpp); + offset_dst = dst_frame_info->offset + + (i_dst * dst_frame_info->pitch) + + (j_dst++ * dst_frame_info->cpp); + offset_src = src_frame_info->offset + + (i * src_frame_info->pitch) + + (j * src_frame_info->cpp); pixel_src = (u8 *)(vaddr_src + offset_src); pixel_dst = (u8 *)(vaddr_dst + offset_dst); @@ -149,32 +149,33 @@ static void blend(void *vaddr_dst, void *vaddr_src, } } -static void compose_plane(struct vkms_composer *primary_composer, - struct vkms_composer *plane_composer, +static void compose_plane(struct vkms_frame_info *primary_plane_info, + struct vkms_frame_info *plane_frame_info, void *vaddr_out) { - struct drm_framebuffer *fb = &plane_composer->fb; + struct drm_framebuffer *fb = &plane_frame_info->fb; void *vaddr; void (*pixel_blend)(const u8 *p_src, u8 *p_dst); - if (WARN_ON(iosys_map_is_null(&plane_composer->map[0]))) + if (WARN_ON(iosys_map_is_null(&plane_frame_info->map[0]))) return; - vaddr = plane_composer->map[0].vaddr; + vaddr = plane_frame_info->map[0].vaddr; if (fb->format->format == DRM_FORMAT_ARGB8888) pixel_blend = &alpha_blend; else pixel_blend = &x_blend; - blend(vaddr_out, vaddr, primary_composer, plane_composer, pixel_blend); + blend(vaddr_out, vaddr, primary_plane_info, + plane_frame_info, pixel_blend); } static int compose_active_planes(void **vaddr_out, - struct vkms_composer *primary_composer, + struct vkms_frame_info *primary_plane_info, struct vkms_crtc_state *crtc_state) { - struct drm_framebuffer *fb = &primary_composer->fb; + struct drm_framebuffer *fb = &primary_plane_info->fb; struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); const void *vaddr; int i; @@ -187,10 +188,10 @@ static int compose_active_planes(void **vaddr_out, } } - if (WARN_ON(iosys_map_is_null(&primary_composer->map[0]))) + if (WARN_ON(iosys_map_is_null(&primary_plane_info->map[0]))) return -EINVAL; - vaddr = primary_composer->map[0].vaddr; + vaddr = primary_plane_info->map[0].vaddr; memcpy(*vaddr_out, vaddr, gem_obj->size); @@ -199,8 +200,8 @@ static int compose_active_planes(void **vaddr_out, * ((primary <- overlay) <- cursor) */ for (i = 1; i < crtc_state->num_active_planes; i++) - compose_plane(primary_composer, - crtc_state->active_planes[i]->composer, + compose_plane(primary_plane_info, + crtc_state->active_planes[i]->frame_info, *vaddr_out); return 0; @@ -222,7 +223,7 @@ void vkms_composer_worker(struct work_struct *work) composer_work); struct drm_crtc *crtc = crtc_state->base.crtc; struct vkms_output *out = drm_crtc_to_vkms_output(crtc); - struct vkms_composer *primary_composer = NULL; + struct vkms_frame_info *primary_plane_info = NULL; struct vkms_plane_state *act_plane = NULL; bool crc_pending, wb_pending; void *vaddr_out = NULL; @@ -250,16 +251,16 @@ void vkms_composer_worker(struct work_struct *work) if (crtc_state->num_active_planes >= 1) { act_plane = crtc_state->active_planes[0]; if (act_plane->base.base.plane->type == DRM_PLANE_TYPE_PRIMARY) - primary_composer = act_plane->composer; + primary_plane_info = act_plane->frame_info; } - if (!primary_composer) + if (!primary_plane_info) return; if (wb_pending) vaddr_out = crtc_state->active_writeback->data[0].vaddr; - ret = compose_active_planes(&vaddr_out, primary_composer, + ret = compose_active_planes(&vaddr_out, primary_plane_info, crtc_state); if (ret) { if (ret == -EINVAL && !wb_pending) @@ -267,7 +268,7 @@ void vkms_composer_worker(struct work_struct *work) return; } - crc32 = compute_crc(vaddr_out, primary_composer); + crc32 = compute_crc(vaddr_out, primary_plane_info); if (wb_pending) { drm_writeback_signal_completion(&out->wb_connector, 0); diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index ae6c5a3d356c..cde7d9ac70ad 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -28,7 +28,7 @@ struct vkms_writeback_job { struct iosys_map data[DRM_FORMAT_MAX_PLANES]; }; -struct vkms_composer { +struct vkms_frame_info { struct drm_framebuffer fb; struct drm_rect src, dst; struct iosys_map map[DRM_FORMAT_MAX_PLANES]; @@ -40,11 +40,11 @@ struct vkms_composer { /** * vkms_plane_state - Driver specific plane state * @base: base plane state - * @composer: data required for composing computation + * @frame_info: data required for composing computation */ struct vkms_plane_state { struct drm_shadow_plane_state base; - struct vkms_composer *composer; + struct vkms_frame_info *frame_info; }; struct vkms_plane { diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 8a810bfa1264..52ec5a691002 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -23,20 +23,20 @@ static struct drm_plane_state * vkms_plane_duplicate_state(struct drm_plane *plane) { struct vkms_plane_state *vkms_state; - struct vkms_composer *composer; + struct vkms_frame_info *frame_info; vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL); if (!vkms_state) return NULL; - composer = kzalloc(sizeof(*composer), GFP_KERNEL); - if (!composer) { - DRM_DEBUG_KMS("Couldn't allocate composer\n"); + frame_info = kzalloc(sizeof(*frame_info), GFP_KERNEL); + if (!frame_info) { + DRM_DEBUG_KMS("Couldn't allocate frame_info\n"); kfree(vkms_state); return NULL; } - vkms_state->composer = composer; + vkms_state->frame_info = frame_info; __drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base); @@ -53,12 +53,12 @@ static void vkms_plane_destroy_state(struct drm_plane *plane, /* dropping the reference we acquired in * vkms_primary_plane_update() */ - if (drm_framebuffer_read_refcount(&vkms_state->composer->fb)) - drm_framebuffer_put(&vkms_state->composer->fb); + if (drm_framebuffer_read_refcount(&vkms_state->frame_info->fb)) + drm_framebuffer_put(&vkms_state->frame_info->fb); } - kfree(vkms_state->composer); - vkms_state->composer = NULL; + kfree(vkms_state->frame_info); + vkms_state->frame_info = NULL; __drm_gem_destroy_shadow_plane_state(&vkms_state->base); kfree(vkms_state); @@ -98,7 +98,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, struct vkms_plane_state *vkms_plane_state; struct drm_shadow_plane_state *shadow_plane_state; struct drm_framebuffer *fb = new_state->fb; - struct vkms_composer *composer; + struct vkms_frame_info *frame_info; if (!new_state->crtc || !fb) return; @@ -106,15 +106,15 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, vkms_plane_state = to_vkms_plane_state(new_state); shadow_plane_state = &vkms_plane_state->base; - composer = vkms_plane_state->composer; - memcpy(&composer->src, &new_state->src, sizeof(struct drm_rect)); - memcpy(&composer->dst, &new_state->dst, sizeof(struct drm_rect)); - memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer)); - memcpy(&composer->map, &shadow_plane_state->data, sizeof(composer->map)); - drm_framebuffer_get(&composer->fb); - composer->offset = fb->offsets[0]; - composer->pitch = fb->pitches[0]; - composer->cpp = fb->format->cpp[0]; + frame_info = vkms_plane_state->frame_info; + memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect)); + memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect)); + memcpy(&frame_info->fb, fb, sizeof(struct drm_framebuffer)); + memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map)); + drm_framebuffer_get(&frame_info->fb); + frame_info->offset = fb->offsets[0]; + frame_info->pitch = fb->pitches[0]; + frame_info->cpp = fb->format->cpp[0]; } static int vkms_plane_atomic_check(struct drm_plane *plane, From 254fe9c106ed69245fbe0beac582054c98a91482 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:05 -0300 Subject: [PATCH 365/396] drm: drm_atomic_helper: Add a new helper to deal with the writeback connector validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper function to validate the connector configuration received in the encoder atomic_check by the drivers. So the drivers don't need to do these common validations themselves. V2: Move the format verification to a new helper at the drm_atomic_helper.c (Thomas Zimmermann). V3: Format check improvements (Leandro Ribeiro). Minor improvements(Thomas Zimmermann). V5: Fix some grammar issues in the commit message (André Almeida). Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-4-igormtorrente@gmail.com --- drivers/gpu/drm/drm_atomic_helper.c | 39 +++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_writeback.c | 9 +++---- include/drm/drm_atomic_helper.h | 3 +++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index d36720f419f7..ee5fea48b5cb 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -785,6 +785,45 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_modeset); +/** + * drm_atomic_helper_check_wb_connector_state() - Check writeback encoder state + * @encoder: encoder state to check + * @conn_state: connector state to check + * + * Checks if the writeback connector state is valid, and returns an error if it + * isn't. + * + * RETURNS: + * Zero for success or -errno + */ +int +drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder, + struct drm_connector_state *conn_state) +{ + struct drm_writeback_job *wb_job = conn_state->writeback_job; + struct drm_property_blob *pixel_format_blob; + struct drm_framebuffer *fb; + size_t i, nformats; + u32 *formats; + + if (!wb_job || !wb_job->fb) + return 0; + + pixel_format_blob = wb_job->connector->pixel_formats_blob_ptr; + nformats = pixel_format_blob->length / sizeof(u32); + formats = pixel_format_blob->data; + fb = wb_job->fb; + + for (i = 0; i < nformats; i++) + if (fb->format->format == formats[i]) + return 0; + + drm_dbg_kms(encoder->dev, "Invalid pixel format %p4cc\n", &fb->format->format); + + return -EINVAL; +} +EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state); + /** * drm_atomic_helper_check_plane_state() - Check plane state for validity * @plane_state: plane state to check diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 3b3c1e757ab4..d427b6c52d03 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -31,6 +31,7 @@ static int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder, { struct drm_framebuffer *fb; const struct drm_display_mode *mode = &crtc_state->mode; + int ret; if (!conn_state->writeback_job || !conn_state->writeback_job->fb) return 0; @@ -42,11 +43,9 @@ static int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder, return -EINVAL; } - if (fb->format->format != vkms_wb_formats[0]) { - DRM_DEBUG_KMS("Invalid pixel format %p4cc\n", - &fb->format->format); - return -EINVAL; - } + ret = drm_atomic_helper_check_wb_encoder_state(encoder, conn_state); + if (ret < 0) + return ret; return 0; } diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 54b321f20d53..06d8902a8097 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -49,6 +49,9 @@ struct drm_private_state; int drm_atomic_helper_check_modeset(struct drm_device *dev, struct drm_atomic_state *state); +int +drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder, + struct drm_connector_state *conn_state); int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, const struct drm_crtc_state *crtc_state, int min_scale, From 2eef1ef6e22b241f26d7bf0f1554a9863277e526 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:06 -0300 Subject: [PATCH 366/396] drm: vkms: get the reference to `drm_framebuffer` instead if coping it Instead of coping `drm_framebuffer` - which can cause problems - we just get the reference and add the ref count. Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-5-igormtorrente@gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 4 ++-- drivers/gpu/drm/vkms/vkms_drv.h | 2 +- drivers/gpu/drm/vkms/vkms_plane.c | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 7c62c5741430..bca049d879e1 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -153,7 +153,7 @@ static void compose_plane(struct vkms_frame_info *primary_plane_info, struct vkms_frame_info *plane_frame_info, void *vaddr_out) { - struct drm_framebuffer *fb = &plane_frame_info->fb; + struct drm_framebuffer *fb = plane_frame_info->fb; void *vaddr; void (*pixel_blend)(const u8 *p_src, u8 *p_dst); @@ -175,7 +175,7 @@ static int compose_active_planes(void **vaddr_out, struct vkms_frame_info *primary_plane_info, struct vkms_crtc_state *crtc_state) { - struct drm_framebuffer *fb = &primary_plane_info->fb; + struct drm_framebuffer *fb = primary_plane_info->fb; struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); const void *vaddr; int i; diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index cde7d9ac70ad..38c44943d915 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -29,7 +29,7 @@ struct vkms_writeback_job { }; struct vkms_frame_info { - struct drm_framebuffer fb; + struct drm_framebuffer *fb; struct drm_rect src, dst; struct iosys_map map[DRM_FORMAT_MAX_PLANES]; unsigned int offset; diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 52ec5a691002..41301d383017 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -49,12 +49,12 @@ static void vkms_plane_destroy_state(struct drm_plane *plane, struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state); struct drm_crtc *crtc = vkms_state->base.base.crtc; - if (crtc) { + if (crtc && vkms_state->frame_info->fb) { /* dropping the reference we acquired in * vkms_primary_plane_update() */ - if (drm_framebuffer_read_refcount(&vkms_state->frame_info->fb)) - drm_framebuffer_put(&vkms_state->frame_info->fb); + if (drm_framebuffer_read_refcount(vkms_state->frame_info->fb)) + drm_framebuffer_put(vkms_state->frame_info->fb); } kfree(vkms_state->frame_info); @@ -109,9 +109,9 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, frame_info = vkms_plane_state->frame_info; memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect)); memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect)); - memcpy(&frame_info->fb, fb, sizeof(struct drm_framebuffer)); + frame_info->fb = fb; memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map)); - drm_framebuffer_get(&frame_info->fb); + drm_framebuffer_get(frame_info->fb); frame_info->offset = fb->offsets[0]; frame_info->pitch = fb->pitches[0]; frame_info->cpp = fb->format->cpp[0]; From bbdf7b2a0b0e69e4e18b5722341dfa6266d19390 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:07 -0300 Subject: [PATCH 367/396] drm: vkms: Add fb information to `vkms_writeback_job` This commit is the groundwork to introduce new formats to the planes and writeback buffer. As part of it, a new buffer metadata field is added to `vkms_writeback_job`, this metadata is represented by the `vkms_frame_info` struct. Also adds two new function pointers (`line_to_frame_func` and `frame_to_line_func`) are defined to handle format conversion from/to internal format. A new internal format(`struct pixel_argb_u16`) is introduced to deal with all possible inputs. It consists of 16 bits fields that represent each of the channels. These things will allow us, in the future, to have different compositing and wb format types. V2: Change the code to get the drm_framebuffer reference and not copy its contents (Thomas Zimmermann). V3: Drop the refcount in the wb code (Thomas Zimmermann). V5: Add {wb,plane}_format_transform_func to vkms_writeback_job and vkms_plane_state (Pekka Paalanen) V6: Improvements to some struct/struct members names (Pekka Paalanen). Splits this patch in two (Pekka Paalanen). V7: Replace line_to_frame_func and frame_to_line_func typedefs with the function signature and void* (Melissa Wen). Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-6-igormtorrente@gmail.com --- drivers/gpu/drm/vkms/vkms_drv.h | 23 ++++++++++++++++++----- drivers/gpu/drm/vkms/vkms_writeback.c | 20 +++++++++++++++++--- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 38c44943d915..0a67b8073f7e 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -23,11 +23,6 @@ #define NUM_OVERLAY_PLANES 8 -struct vkms_writeback_job { - struct iosys_map map[DRM_FORMAT_MAX_PLANES]; - struct iosys_map data[DRM_FORMAT_MAX_PLANES]; -}; - struct vkms_frame_info { struct drm_framebuffer *fb; struct drm_rect src, dst; @@ -37,6 +32,22 @@ struct vkms_frame_info { unsigned int cpp; }; +struct pixel_argb_u16 { + u16 a, r, g, b; +}; + +struct line_buffer { + size_t n_pixels; + struct pixel_argb_u16 *pixels; +}; + +struct vkms_writeback_job { + struct iosys_map data[DRM_FORMAT_MAX_PLANES]; + struct vkms_frame_info wb_frame_info; + void (*wb_write)(struct vkms_frame_info *frame_info, + const struct line_buffer *buffer, int y); +}; + /** * vkms_plane_state - Driver specific plane state * @base: base plane state @@ -45,6 +56,8 @@ struct vkms_frame_info { struct vkms_plane_state { struct drm_shadow_plane_state base; struct vkms_frame_info *frame_info; + void (*plane_read)(struct line_buffer *buffer, + const struct vkms_frame_info *frame_info, int y); }; struct vkms_plane { diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index d427b6c52d03..e0a1ba378fc9 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -75,12 +75,15 @@ static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector, if (!vkmsjob) return -ENOMEM; - ret = drm_gem_fb_vmap(job->fb, vkmsjob->map, vkmsjob->data); + ret = drm_gem_fb_vmap(job->fb, vkmsjob->wb_frame_info.map, vkmsjob->data); if (ret) { DRM_ERROR("vmap failed: %d\n", ret); goto err_kfree; } + vkmsjob->wb_frame_info.fb = job->fb; + drm_framebuffer_get(vkmsjob->wb_frame_info.fb); + job->priv = vkmsjob; return 0; @@ -99,7 +102,9 @@ static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector, if (!job->fb) return; - drm_gem_fb_vunmap(job->fb, vkmsjob->map); + drm_gem_fb_vunmap(job->fb, vkmsjob->wb_frame_info.map); + + drm_framebuffer_put(vkmsjob->wb_frame_info.fb); vkmsdev = drm_device_to_vkms_device(job->fb->dev); vkms_set_composer(&vkmsdev->output, false); @@ -116,14 +121,23 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, struct drm_writeback_connector *wb_conn = &output->wb_connector; struct drm_connector_state *conn_state = wb_conn->base.state; struct vkms_crtc_state *crtc_state = output->composer_state; + struct drm_framebuffer *fb = connector_state->writeback_job->fb; + struct vkms_writeback_job *active_wb; + struct vkms_frame_info *wb_frame_info; if (!conn_state) return; vkms_set_composer(&vkmsdev->output, true); + active_wb = conn_state->writeback_job->priv; + wb_frame_info = &active_wb->wb_frame_info; + spin_lock_irq(&output->composer_lock); - crtc_state->active_writeback = conn_state->writeback_job->priv; + crtc_state->active_writeback = active_wb; + wb_frame_info->offset = fb->offsets[0]; + wb_frame_info->pitch = fb->pitches[0]; + wb_frame_info->cpp = fb->format->cpp[0]; crtc_state->wb_pending = true; spin_unlock_irq(&output->composer_lock); drm_writeback_queue_job(wb_conn, connector_state); From 8ba1648567e289c90fa4f65b4204d0f160e22ac3 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:08 -0300 Subject: [PATCH 368/396] drm: vkms: Refactor the plane composer to accept new formats Currently the blend function only accepts XRGB_8888 and ARGB_8888 as a color input. This patch refactors all the functions related to the plane composition to overcome this limitation. The pixels blend is done using the new internal format. And new handlers are being added to convert a specific format to/from this internal format. So the blend operation depends on these handlers to convert to this common format. The blended result, if necessary, is converted to the writeback buffer format. This patch introduces three major differences to the blend function. 1 - All the planes are blended at once. 2 - The blend calculus is done as per line instead of per pixel. 3 - It is responsible to calculates the CRC and writing the writeback buffer(if necessary). These changes allow us to allocate way less memory in the intermediate buffer to compute these operations. Because now we don't need to have the entire intermediate image lines at once, just one line is enough. | Memory consumption (output dimensions) | |:--------------------------------------:| | Current | This patch | |:------------------:|:-----------------:| | Width * Heigth | 2 * Width | Beyond memory, we also have a minor performance benefit from all these changes. Results running the IGT[1] test `igt@kms_cursor_crc@pipe-a-cursor-512x512-onscreen` ten times: | Frametime | |:------------------------------------------:| | Implementation | Current | This commit | |:---------------:|:---------:|:------------:| | frametime range | 9~22 ms | 5~17 ms | | Average | 11.4 ms | 7.8 ms | [1] IGT commit id: bc3f6833a12221a46659535dac06ebb312490eb4 V2: Improves the performance drastically, by performing the operations per-line and not per-pixel(Pekka Paalanen). Minor improvements(Pekka Paalanen). V3: Changes the code to blend the planes all at once. This improves performance, memory consumption, and removes much of the weirdness of the V2(Pekka Paalanen and me). Minor improvements(Pekka Paalanen and me). V4: Rebase the code and adapt it to the new NUM_OVERLAY_PLANES constant. V5: Minor checkpatch fixes and the removal of TO-DO item(Melissa Wen). Several security/robustness improvents(Pekka Paalanen). Removes check_planes_x_bounds function and allows partial partly off-screen(Pekka Paalanen). V6: Fix a mismatch of some variable sizes (Pekka Paalanen). Several minor improvements (Pekka Paalanen). Reviewed-by: Melissa Wen <mwen@igalia.com> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-7-igormtorrente@gmail.com --- Documentation/gpu/vkms.rst | 4 - drivers/gpu/drm/vkms/Makefile | 1 + drivers/gpu/drm/vkms/vkms_composer.c | 344 ++++++++++++-------------- drivers/gpu/drm/vkms/vkms_formats.c | 155 ++++++++++++ drivers/gpu/drm/vkms/vkms_formats.h | 12 + drivers/gpu/drm/vkms/vkms_plane.c | 3 + drivers/gpu/drm/vkms/vkms_writeback.c | 3 + 7 files changed, 329 insertions(+), 193 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_formats.c create mode 100644 drivers/gpu/drm/vkms/vkms_formats.h diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index 973e2d43108b..a49e4ae92653 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -118,10 +118,6 @@ Add Plane Features There's lots of plane features we could add support for: -- Clearing primary plane: clear primary plane before plane composition (at the - start) for correctness of pixel blend ops. It also guarantees alpha channel - is cleared in the target buffer for stable crc. [Good to get started] - - ARGB format on primary plane: blend the primary plane into background with translucent alpha. diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 72f779cbfedd..1b28a6a32948 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -3,6 +3,7 @@ vkms-y := \ vkms_drv.o \ vkms_plane.o \ vkms_output.o \ + vkms_formats.o \ vkms_crtc.o \ vkms_composer.o \ vkms_writeback.o diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index bca049d879e1..5b1a8bdd8268 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -7,204 +7,188 @@ #include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_vblank.h> +#include <linux/minmax.h> #include "vkms_drv.h" -static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer, - const struct vkms_frame_info *frame_info) +static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha) { - u32 pixel; - int src_offset = frame_info->offset + (y * frame_info->pitch) - + (x * frame_info->cpp); + u32 new_color; - pixel = *(u32 *)&buffer[src_offset]; + new_color = (src * 0xffff + dst * (0xffff - alpha)); - return pixel; + return DIV_ROUND_CLOSEST(new_color, 0xffff); } /** - * compute_crc - Compute CRC value on output frame - * - * @vaddr: address to final framebuffer - * @frame_info: framebuffer's metadata - * - * returns CRC value computed using crc32 on the visible portion of - * the final framebuffer at vaddr_out - */ -static uint32_t compute_crc(const u8 *vaddr, - const struct vkms_frame_info *frame_info) -{ - int x, y; - u32 crc = 0, pixel = 0; - int x_src = frame_info->src.x1 >> 16; - int y_src = frame_info->src.y1 >> 16; - int h_src = drm_rect_height(&frame_info->src) >> 16; - int w_src = drm_rect_width(&frame_info->src) >> 16; - - for (y = y_src; y < y_src + h_src; ++y) { - for (x = x_src; x < x_src + w_src; ++x) { - pixel = get_pixel_from_buffer(x, y, vaddr, frame_info); - crc = crc32_le(crc, (void *)&pixel, sizeof(u32)); - } - } - - return crc; -} - -static u8 blend_channel(u8 src, u8 dst, u8 alpha) -{ - u32 pre_blend; - u8 new_color; - - pre_blend = (src * 255 + dst * (255 - alpha)); - - /* Faster div by 255 */ - new_color = ((pre_blend + ((pre_blend + 257) >> 8)) >> 8); - - return new_color; -} - -/** - * alpha_blend - alpha blending equation - * @argb_src: src pixel on premultiplied alpha mode - * @argb_dst: dst pixel completely opaque - * - * blend pixels using premultiplied blend formula. The current DRM assumption - * is that pixel color values have been already pre-multiplied with the alpha - * channel values. See more drm_plane_create_blend_mode_property(). Also, this - * formula assumes a completely opaque background. - */ -static void alpha_blend(const u8 *argb_src, u8 *argb_dst) -{ - u8 alpha; - - alpha = argb_src[3]; - argb_dst[0] = blend_channel(argb_src[0], argb_dst[0], alpha); - argb_dst[1] = blend_channel(argb_src[1], argb_dst[1], alpha); - argb_dst[2] = blend_channel(argb_src[2], argb_dst[2], alpha); -} - -/** - * x_blend - blending equation that ignores the pixel alpha - * - * overwrites RGB color value from src pixel to dst pixel. - */ -static void x_blend(const u8 *xrgb_src, u8 *xrgb_dst) -{ - memcpy(xrgb_dst, xrgb_src, sizeof(u8) * 3); -} - -/** - * blend - blend value at vaddr_src with value at vaddr_dst - * @vaddr_dst: destination address - * @vaddr_src: source address - * @dst_frame_info: destination framebuffer's metadata + * pre_mul_alpha_blend - alpha blending equation * @src_frame_info: source framebuffer's metadata - * @pixel_blend: blending equation based on plane format + * @stage_buffer: The line with the pixels from src_plane + * @output_buffer: A line buffer that receives all the blends output * - * Blend the vaddr_src value with the vaddr_dst value using a pixel blend - * equation according to the supported plane formats DRM_FORMAT_(A/XRGB8888) - * and clearing alpha channel to an completely opaque background. This function - * uses buffer's metadata to locate the new composite values at vaddr_dst. + * Using the information from the `frame_info`, this blends only the + * necessary pixels from the `stage_buffer` to the `output_buffer` + * using premultiplied blend formula. * - * TODO: completely clear the primary plane (a = 0xff) before starting to blend - * pixel color values + * The current DRM assumption is that pixel color values have been already + * pre-multiplied with the alpha channel values. See more + * drm_plane_create_blend_mode_property(). Also, this formula assumes a + * completely opaque background. */ -static void blend(void *vaddr_dst, void *vaddr_src, - struct vkms_frame_info *dst_frame_info, - struct vkms_frame_info *src_frame_info, - void (*pixel_blend)(const u8 *, u8 *)) +static void pre_mul_alpha_blend(struct vkms_frame_info *frame_info, + struct line_buffer *stage_buffer, + struct line_buffer *output_buffer) { - int i, j, j_dst, i_dst; - int offset_src, offset_dst; - u8 *pixel_dst, *pixel_src; + int x_dst = frame_info->dst.x1; + struct pixel_argb_u16 *out = output_buffer->pixels + x_dst; + struct pixel_argb_u16 *in = stage_buffer->pixels; + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + stage_buffer->n_pixels); - int x_src = src_frame_info->src.x1 >> 16; - int y_src = src_frame_info->src.y1 >> 16; - - int x_dst = src_frame_info->dst.x1; - int y_dst = src_frame_info->dst.y1; - int h_dst = drm_rect_height(&src_frame_info->dst); - int w_dst = drm_rect_width(&src_frame_info->dst); - - int y_limit = y_src + h_dst; - int x_limit = x_src + w_dst; - - for (i = y_src, i_dst = y_dst; i < y_limit; ++i) { - for (j = x_src, j_dst = x_dst; j < x_limit; ++j) { - offset_dst = dst_frame_info->offset - + (i_dst * dst_frame_info->pitch) - + (j_dst++ * dst_frame_info->cpp); - offset_src = src_frame_info->offset - + (i * src_frame_info->pitch) - + (j * src_frame_info->cpp); - - pixel_src = (u8 *)(vaddr_src + offset_src); - pixel_dst = (u8 *)(vaddr_dst + offset_dst); - pixel_blend(pixel_src, pixel_dst); - /* clearing alpha channel (0xff)*/ - pixel_dst[3] = 0xff; - } - i_dst++; + for (int x = 0; x < x_limit; x++) { + out[x].a = (u16)0xffff; + out[x].r = pre_mul_blend_channel(in[x].r, out[x].r, in[x].a); + out[x].g = pre_mul_blend_channel(in[x].g, out[x].g, in[x].a); + out[x].b = pre_mul_blend_channel(in[x].b, out[x].b, in[x].a); } } -static void compose_plane(struct vkms_frame_info *primary_plane_info, - struct vkms_frame_info *plane_frame_info, - void *vaddr_out) +static bool check_y_limit(struct vkms_frame_info *frame_info, int y) { - struct drm_framebuffer *fb = plane_frame_info->fb; - void *vaddr; - void (*pixel_blend)(const u8 *p_src, u8 *p_dst); + if (y >= frame_info->dst.y1 && y < frame_info->dst.y2) + return true; - if (WARN_ON(iosys_map_is_null(&plane_frame_info->map[0]))) - return; - - vaddr = plane_frame_info->map[0].vaddr; - - if (fb->format->format == DRM_FORMAT_ARGB8888) - pixel_blend = &alpha_blend; - else - pixel_blend = &x_blend; - - blend(vaddr_out, vaddr, primary_plane_info, - plane_frame_info, pixel_blend); + return false; } -static int compose_active_planes(void **vaddr_out, - struct vkms_frame_info *primary_plane_info, - struct vkms_crtc_state *crtc_state) +/** + * @wb_frame_info: The writeback frame buffer metadata + * @crtc_state: The crtc state + * @crc32: The crc output of the final frame + * @output_buffer: A buffer of a row that will receive the result of the blend(s) + * @stage_buffer: The line with the pixels from plane being blend to the output + * + * This function blends the pixels (Using the `pre_mul_alpha_blend`) + * from all planes, calculates the crc32 of the output from the former step, + * and, if necessary, convert and store the output to the writeback buffer. + */ +static void blend(struct vkms_writeback_job *wb, + struct vkms_crtc_state *crtc_state, + u32 *crc32, struct line_buffer *stage_buffer, + struct line_buffer *output_buffer, size_t row_size) { - struct drm_framebuffer *fb = primary_plane_info->fb; - struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); - const void *vaddr; - int i; + struct vkms_plane_state **plane = crtc_state->active_planes; + struct vkms_frame_info *primary_plane_info = plane[0]->frame_info; + u32 n_active_planes = crtc_state->num_active_planes; - if (!*vaddr_out) { - *vaddr_out = kvzalloc(gem_obj->size, GFP_KERNEL); - if (!*vaddr_out) { - DRM_ERROR("Cannot allocate memory for output frame."); - return -ENOMEM; + int y_dst = primary_plane_info->dst.y1; + int h_dst = drm_rect_height(&primary_plane_info->dst); + int y_limit = y_dst + h_dst; + + for (size_t y = y_dst; y < y_limit; y++) { + plane[0]->plane_read(output_buffer, primary_plane_info, y); + + /* If there are other planes besides primary, we consider the active + * planes should be in z-order and compose them associatively: + * ((primary <- overlay) <- cursor) + */ + for (size_t i = 1; i < n_active_planes; i++) { + if (!check_y_limit(plane[i]->frame_info, y)) + continue; + + plane[i]->plane_read(stage_buffer, plane[i]->frame_info, y); + pre_mul_alpha_blend(plane[i]->frame_info, stage_buffer, + output_buffer); } + + *crc32 = crc32_le(*crc32, (void *)output_buffer->pixels, row_size); + + if (wb) + wb->wb_write(&wb->wb_frame_info, output_buffer, y); } +} + +static int check_format_funcs(struct vkms_crtc_state *crtc_state, + struct vkms_writeback_job *active_wb) +{ + struct vkms_plane_state **planes = crtc_state->active_planes; + u32 n_active_planes = crtc_state->num_active_planes; + + for (size_t i = 0; i < n_active_planes; i++) + if (!planes[i]->plane_read) + return -1; + + if (active_wb && !active_wb->wb_write) + return -1; + + return 0; +} + +static int compose_active_planes(struct vkms_writeback_job *active_wb, + struct vkms_crtc_state *crtc_state, + u32 *crc32) +{ + size_t line_width, pixel_size = sizeof(struct pixel_argb_u16); + struct vkms_frame_info *primary_plane_info = NULL; + struct line_buffer output_buffer, stage_buffer; + struct vkms_plane_state *act_plane = NULL; + int ret = 0; + + /* + * This check exists so we can call `crc32_le` for the entire line + * instead doing it for each channel of each pixel in case + * `struct `pixel_argb_u16` had any gap added by the compiler + * between the struct fields. + */ + static_assert(sizeof(struct pixel_argb_u16) == 8); + + if (crtc_state->num_active_planes >= 1) { + act_plane = crtc_state->active_planes[0]; + if (act_plane->base.base.plane->type == DRM_PLANE_TYPE_PRIMARY) + primary_plane_info = act_plane->frame_info; + } + + if (!primary_plane_info) + return -EINVAL; if (WARN_ON(iosys_map_is_null(&primary_plane_info->map[0]))) return -EINVAL; - vaddr = primary_plane_info->map[0].vaddr; + if (WARN_ON(check_format_funcs(crtc_state, active_wb))) + return -EINVAL; - memcpy(*vaddr_out, vaddr, gem_obj->size); + line_width = drm_rect_width(&primary_plane_info->dst); + stage_buffer.n_pixels = line_width; + output_buffer.n_pixels = line_width; - /* If there are other planes besides primary, we consider the active - * planes should be in z-order and compose them associatively: - * ((primary <- overlay) <- cursor) - */ - for (i = 1; i < crtc_state->num_active_planes; i++) - compose_plane(primary_plane_info, - crtc_state->active_planes[i]->frame_info, - *vaddr_out); + stage_buffer.pixels = kvmalloc(line_width * pixel_size, GFP_KERNEL); + if (!stage_buffer.pixels) { + DRM_ERROR("Cannot allocate memory for the output line buffer"); + return -ENOMEM; + } - return 0; + output_buffer.pixels = kvmalloc(line_width * pixel_size, GFP_KERNEL); + if (!output_buffer.pixels) { + DRM_ERROR("Cannot allocate memory for intermediate line buffer"); + ret = -ENOMEM; + goto free_stage_buffer; + } + + if (active_wb) { + struct vkms_frame_info *wb_frame_info = &active_wb->wb_frame_info; + + wb_frame_info->src = primary_plane_info->src; + wb_frame_info->dst = primary_plane_info->dst; + } + + blend(active_wb, crtc_state, crc32, &stage_buffer, + &output_buffer, line_width * pixel_size); + + kvfree(output_buffer.pixels); +free_stage_buffer: + kvfree(stage_buffer.pixels); + + return ret; } /** @@ -222,13 +206,11 @@ void vkms_composer_worker(struct work_struct *work) struct vkms_crtc_state, composer_work); struct drm_crtc *crtc = crtc_state->base.crtc; + struct vkms_writeback_job *active_wb = crtc_state->active_writeback; struct vkms_output *out = drm_crtc_to_vkms_output(crtc); - struct vkms_frame_info *primary_plane_info = NULL; - struct vkms_plane_state *act_plane = NULL; bool crc_pending, wb_pending; - void *vaddr_out = NULL; - u32 crc32 = 0; u64 frame_start, frame_end; + u32 crc32 = 0; int ret; spin_lock_irq(&out->composer_lock); @@ -248,35 +230,19 @@ void vkms_composer_worker(struct work_struct *work) if (!crc_pending) return; - if (crtc_state->num_active_planes >= 1) { - act_plane = crtc_state->active_planes[0]; - if (act_plane->base.base.plane->type == DRM_PLANE_TYPE_PRIMARY) - primary_plane_info = act_plane->frame_info; - } - - if (!primary_plane_info) - return; - if (wb_pending) - vaddr_out = crtc_state->active_writeback->data[0].vaddr; + ret = compose_active_planes(active_wb, crtc_state, &crc32); + else + ret = compose_active_planes(NULL, crtc_state, &crc32); - ret = compose_active_planes(&vaddr_out, primary_plane_info, - crtc_state); - if (ret) { - if (ret == -EINVAL && !wb_pending) - kvfree(vaddr_out); + if (ret) return; - } - - crc32 = compute_crc(vaddr_out, primary_plane_info); if (wb_pending) { drm_writeback_signal_completion(&out->wb_connector, 0); spin_lock_irq(&out->composer_lock); crtc_state->wb_pending = false; spin_unlock_irq(&out->composer_lock); - } else { - kvfree(vaddr_out); } /* diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c new file mode 100644 index 000000000000..33803d3e30b7 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <drm/drm_rect.h> +#include <linux/minmax.h> + +#include "vkms_formats.h" + +static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int y) +{ + return frame_info->offset + (y * frame_info->pitch) + + (x * frame_info->cpp); +} + +/* + * packed_pixels_addr - Get the pointer to pixel of a given pair of coordinates + * + * @frame_info: Buffer metadata + * @x: The x(width) coordinate of the 2D buffer + * @y: The y(Heigth) coordinate of the 2D buffer + * + * Takes the information stored in the frame_info, a pair of coordinates, and + * returns the address of the first color channel. + * This function assumes the channels are packed together, i.e. a color channel + * comes immediately after another in the memory. And therefore, this function + * doesn't work for YUV with chroma subsampling (e.g. YUV420 and NV21). + */ +static void *packed_pixels_addr(const struct vkms_frame_info *frame_info, + int x, int y) +{ + size_t offset = pixel_offset(frame_info, x, y); + + return (u8 *)frame_info->map[0].vaddr + offset; +} + +static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y) +{ + int x_src = frame_info->src.x1 >> 16; + int y_src = y - frame_info->dst.y1 + (frame_info->src.y1 >> 16); + + return packed_pixels_addr(frame_info, x_src, y_src); +} + +static void ARGB8888_to_argb_u16(struct line_buffer *stage_buffer, + const struct vkms_frame_info *frame_info, int y) +{ + struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; + u8 *src_pixels = get_packed_src_addr(frame_info, y); + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + stage_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { + /* + * The 257 is the "conversion ratio". This number is obtained by the + * (2^16 - 1) / (2^8 - 1) division. Which, in this case, tries to get + * the best color value in a pixel format with more possibilities. + * A similar idea applies to others RGB color conversions. + */ + out_pixels[x].a = (u16)src_pixels[3] * 257; + out_pixels[x].r = (u16)src_pixels[2] * 257; + out_pixels[x].g = (u16)src_pixels[1] * 257; + out_pixels[x].b = (u16)src_pixels[0] * 257; + } +} + +static void XRGB8888_to_argb_u16(struct line_buffer *stage_buffer, + const struct vkms_frame_info *frame_info, int y) +{ + struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; + u8 *src_pixels = get_packed_src_addr(frame_info, y); + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + stage_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { + out_pixels[x].a = (u16)0xffff; + out_pixels[x].r = (u16)src_pixels[2] * 257; + out_pixels[x].g = (u16)src_pixels[1] * 257; + out_pixels[x].b = (u16)src_pixels[0] * 257; + } +} + +/* + * The following functions take an line of argb_u16 pixels from the + * src_buffer, convert them to a specific format, and store them in the + * destination. + * + * They are used in the `compose_active_planes` to convert and store a line + * from the src_buffer to the writeback buffer. + */ +static void argb_u16_to_ARGB8888(struct vkms_frame_info *frame_info, + const struct line_buffer *src_buffer, int y) +{ + int x_dst = frame_info->dst.x1; + u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y); + struct pixel_argb_u16 *in_pixels = src_buffer->pixels; + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + src_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) { + /* + * This sequence below is important because the format's byte order is + * in little-endian. In the case of the ARGB8888 the memory is + * organized this way: + * + * | Addr | = blue channel + * | Addr + 1 | = green channel + * | Addr + 2 | = Red channel + * | Addr + 3 | = Alpha channel + */ + dst_pixels[3] = DIV_ROUND_CLOSEST(in_pixels[x].a, 257); + dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixels[x].r, 257); + dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixels[x].g, 257); + dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixels[x].b, 257); + } +} + +static void argb_u16_to_XRGB8888(struct vkms_frame_info *frame_info, + const struct line_buffer *src_buffer, int y) +{ + int x_dst = frame_info->dst.x1; + u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y); + struct pixel_argb_u16 *in_pixels = src_buffer->pixels; + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + src_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) { + dst_pixels[3] = 0xff; + dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixels[x].r, 257); + dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixels[x].g, 257); + dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixels[x].b, 257); + } +} + +void *get_frame_to_line_function(u32 format) +{ + switch (format) { + case DRM_FORMAT_ARGB8888: + return &ARGB8888_to_argb_u16; + case DRM_FORMAT_XRGB8888: + return &XRGB8888_to_argb_u16; + default: + return NULL; + } +} + +void *get_line_to_frame_function(u32 format) +{ + switch (format) { + case DRM_FORMAT_ARGB8888: + return &argb_u16_to_ARGB8888; + case DRM_FORMAT_XRGB8888: + return &argb_u16_to_XRGB8888; + default: + return NULL; + } +} diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h new file mode 100644 index 000000000000..43b7c1979018 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _VKMS_FORMATS_H_ +#define _VKMS_FORMATS_H_ + +#include "vkms_drv.h" + +void *get_frame_to_line_function(u32 format); + +void *get_line_to_frame_function(u32 format); + +#endif /* _VKMS_FORMATS_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 41301d383017..d5f3fbfc0f7c 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -9,6 +9,7 @@ #include <drm/drm_gem_framebuffer_helper.h> #include "vkms_drv.h" +#include "vkms_formats.h" static const u32 vkms_formats[] = { DRM_FORMAT_XRGB8888, @@ -99,6 +100,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, struct drm_shadow_plane_state *shadow_plane_state; struct drm_framebuffer *fb = new_state->fb; struct vkms_frame_info *frame_info; + u32 fmt = fb->format->format; if (!new_state->crtc || !fb) return; @@ -115,6 +117,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, frame_info->offset = fb->offsets[0]; frame_info->pitch = fb->pitches[0]; frame_info->cpp = fb->format->cpp[0]; + vkms_plane_state->plane_read = get_frame_to_line_function(fmt); } static int vkms_plane_atomic_check(struct drm_plane *plane, diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index e0a1ba378fc9..d10dd4de8608 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -12,6 +12,7 @@ #include <drm/drm_gem_shmem_helper.h> #include "vkms_drv.h" +#include "vkms_formats.h" static const u32 vkms_wb_formats[] = { DRM_FORMAT_XRGB8888, @@ -124,6 +125,7 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, struct drm_framebuffer *fb = connector_state->writeback_job->fb; struct vkms_writeback_job *active_wb; struct vkms_frame_info *wb_frame_info; + u32 wb_format = fb->format->format; if (!conn_state) return; @@ -141,6 +143,7 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, crtc_state->wb_pending = true; spin_unlock_irq(&output->composer_lock); drm_writeback_queue_job(wb_conn, connector_state); + active_wb->wb_write = get_line_to_frame_function(wb_format); } static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = { From bc0d7fdefec62e0cb83c1bcd3c7bd033f5e826e0 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:09 -0300 Subject: [PATCH 369/396] drm: vkms: Supports to the case where primary plane doesn't match the CRTC We will remove the current assumption that the primary plane has the same size and position as CRTC and that the primary plane is the bottom-most in zpos order, or is even enabled. At least as far as the blending machinery is concerned. For that we will add CRTC dimension information to `vkms_crtc_state` and add a opaque black backgound color. Because now we need to fill the background, we had a loss in performance with this change. Results running the IGT[1] test `igt@kms_cursor_crc@pipe-a-cursor-512x512-onscreen` ten times: | Frametime | |:--------------------------------------------:| | Implementation | Previous | This commit | |:---------------:|:---------:|:--------------:| | frametime range | 5~18 ms | 10~22 ms | | Average | 8.47 ms | 12.32 ms | [1] IGT commit id: bc3f6833a12221a46659535dac06ebb312490eb4 V6: Improve the commit description (Pekka Paalanen). Update some comments (Pekka Paalanen). Remove some fields from `vkms_crtc_state` and move where some variables are set (Pekka Paalanen). Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-8-igormtorrente@gmail.com --- Documentation/gpu/vkms.rst | 3 +- drivers/gpu/drm/vkms/vkms_composer.c | 59 +++++++++++++-------------- drivers/gpu/drm/vkms/vkms_writeback.c | 4 ++ 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index a49e4ae92653..49db221c0f52 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -121,8 +121,7 @@ There's lots of plane features we could add support for: - ARGB format on primary plane: blend the primary plane into background with translucent alpha. -- Support when the primary plane isn't exactly matching the output size: blend - the primary plane into the black background. +- Add background color KMS property[Good to get started]. - Full alpha blending on all planes. diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 5b1a8bdd8268..8e53fa80742b 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -61,6 +61,13 @@ static bool check_y_limit(struct vkms_frame_info *frame_info, int y) return false; } +static void fill_background(const struct pixel_argb_u16 *background_color, + struct line_buffer *output_buffer) +{ + for (size_t i = 0; i < output_buffer->n_pixels; i++) + output_buffer->pixels[i] = *background_color; +} + /** * @wb_frame_info: The writeback frame buffer metadata * @crtc_state: The crtc state @@ -78,21 +85,17 @@ static void blend(struct vkms_writeback_job *wb, struct line_buffer *output_buffer, size_t row_size) { struct vkms_plane_state **plane = crtc_state->active_planes; - struct vkms_frame_info *primary_plane_info = plane[0]->frame_info; u32 n_active_planes = crtc_state->num_active_planes; - int y_dst = primary_plane_info->dst.y1; - int h_dst = drm_rect_height(&primary_plane_info->dst); - int y_limit = y_dst + h_dst; + const struct pixel_argb_u16 background_color = { .a = 0xffff }; - for (size_t y = y_dst; y < y_limit; y++) { - plane[0]->plane_read(output_buffer, primary_plane_info, y); + size_t crtc_y_limit = crtc_state->base.crtc->mode.vdisplay; - /* If there are other planes besides primary, we consider the active - * planes should be in z-order and compose them associatively: - * ((primary <- overlay) <- cursor) - */ - for (size_t i = 1; i < n_active_planes; i++) { + for (size_t y = 0; y < crtc_y_limit; y++) { + fill_background(&background_color, output_buffer); + + /* The active planes are composed associatively in z-order. */ + for (size_t i = 0; i < n_active_planes; i++) { if (!check_y_limit(plane[i]->frame_info, y)) continue; @@ -124,14 +127,24 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state, return 0; } +static int check_iosys_map(struct vkms_crtc_state *crtc_state) +{ + struct vkms_plane_state **plane_state = crtc_state->active_planes; + u32 n_active_planes = crtc_state->num_active_planes; + + for (size_t i = 0; i < n_active_planes; i++) + if (iosys_map_is_null(&plane_state[i]->frame_info->map[0])) + return -1; + + return 0; +} + static int compose_active_planes(struct vkms_writeback_job *active_wb, struct vkms_crtc_state *crtc_state, u32 *crc32) { size_t line_width, pixel_size = sizeof(struct pixel_argb_u16); - struct vkms_frame_info *primary_plane_info = NULL; struct line_buffer output_buffer, stage_buffer; - struct vkms_plane_state *act_plane = NULL; int ret = 0; /* @@ -142,22 +155,13 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb, */ static_assert(sizeof(struct pixel_argb_u16) == 8); - if (crtc_state->num_active_planes >= 1) { - act_plane = crtc_state->active_planes[0]; - if (act_plane->base.base.plane->type == DRM_PLANE_TYPE_PRIMARY) - primary_plane_info = act_plane->frame_info; - } - - if (!primary_plane_info) - return -EINVAL; - - if (WARN_ON(iosys_map_is_null(&primary_plane_info->map[0]))) + if (WARN_ON(check_iosys_map(crtc_state))) return -EINVAL; if (WARN_ON(check_format_funcs(crtc_state, active_wb))) return -EINVAL; - line_width = drm_rect_width(&primary_plane_info->dst); + line_width = crtc_state->base.crtc->mode.hdisplay; stage_buffer.n_pixels = line_width; output_buffer.n_pixels = line_width; @@ -174,13 +178,6 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb, goto free_stage_buffer; } - if (active_wb) { - struct vkms_frame_info *wb_frame_info = &active_wb->wb_frame_info; - - wb_frame_info->src = primary_plane_info->src; - wb_frame_info->dst = primary_plane_info->dst; - } - blend(active_wb, crtc_state, crc32, &stage_buffer, &output_buffer, line_width * pixel_size); diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index d10dd4de8608..0ce5e28d260d 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -123,6 +123,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, struct drm_connector_state *conn_state = wb_conn->base.state; struct vkms_crtc_state *crtc_state = output->composer_state; struct drm_framebuffer *fb = connector_state->writeback_job->fb; + u16 crtc_height = crtc_state->base.crtc->mode.vdisplay; + u16 crtc_width = crtc_state->base.crtc->mode.hdisplay; struct vkms_writeback_job *active_wb; struct vkms_frame_info *wb_frame_info; u32 wb_format = fb->format->format; @@ -144,6 +146,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, spin_unlock_irq(&output->composer_lock); drm_writeback_queue_job(wb_conn, connector_state); active_wb->wb_write = get_line_to_frame_function(wb_format); + drm_rect_init(&wb_frame_info->src, 0, 0, crtc_width, crtc_height); + drm_rect_init(&wb_frame_info->dst, 0, 0, crtc_width, crtc_height); } static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = { From 3675d8a1726337bd1e839a185e0a7ce0bc459b6b Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:10 -0300 Subject: [PATCH 370/396] drm: vkms: Adds XRGB_16161616 and ARGB_1616161616 formats This will be useful to write tests that depends on these formats. ARGB and XRGB follows the a similar implementation of the former formats. Just adjusting for 16 bits per channel. V3: Adapt the handlers to the new format introduced in patch 7 V3. V5: Minor improvements Added le16_to_cpu/cpu_to_le16 to the 16 bits color read/writes. Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-9-igormtorrente@gmail.com --- drivers/gpu/drm/vkms/vkms_formats.c | 76 +++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_plane.c | 5 +- drivers/gpu/drm/vkms/vkms_writeback.c | 2 + 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 33803d3e30b7..3af36476a7df 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -78,6 +78,40 @@ static void XRGB8888_to_argb_u16(struct line_buffer *stage_buffer, } } +static void ARGB16161616_to_argb_u16(struct line_buffer *stage_buffer, + const struct vkms_frame_info *frame_info, + int y) +{ + struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; + u16 *src_pixels = get_packed_src_addr(frame_info, y); + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + stage_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { + out_pixels[x].a = le16_to_cpu(src_pixels[3]); + out_pixels[x].r = le16_to_cpu(src_pixels[2]); + out_pixels[x].g = le16_to_cpu(src_pixels[1]); + out_pixels[x].b = le16_to_cpu(src_pixels[0]); + } +} + +static void XRGB16161616_to_argb_u16(struct line_buffer *stage_buffer, + const struct vkms_frame_info *frame_info, + int y) +{ + struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; + u16 *src_pixels = get_packed_src_addr(frame_info, y); + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + stage_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, src_pixels += 4) { + out_pixels[x].a = (u16)0xffff; + out_pixels[x].r = le16_to_cpu(src_pixels[2]); + out_pixels[x].g = le16_to_cpu(src_pixels[1]); + out_pixels[x].b = le16_to_cpu(src_pixels[0]); + } +} + /* * The following functions take an line of argb_u16 pixels from the * src_buffer, convert them to a specific format, and store them in the @@ -130,6 +164,40 @@ static void argb_u16_to_XRGB8888(struct vkms_frame_info *frame_info, } } +static void argb_u16_to_ARGB16161616(struct vkms_frame_info *frame_info, + const struct line_buffer *src_buffer, int y) +{ + int x_dst = frame_info->dst.x1; + u16 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y); + struct pixel_argb_u16 *in_pixels = src_buffer->pixels; + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + src_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) { + dst_pixels[3] = cpu_to_le16(in_pixels[x].a); + dst_pixels[2] = cpu_to_le16(in_pixels[x].r); + dst_pixels[1] = cpu_to_le16(in_pixels[x].g); + dst_pixels[0] = cpu_to_le16(in_pixels[x].b); + } +} + +static void argb_u16_to_XRGB16161616(struct vkms_frame_info *frame_info, + const struct line_buffer *src_buffer, int y) +{ + int x_dst = frame_info->dst.x1; + u16 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y); + struct pixel_argb_u16 *in_pixels = src_buffer->pixels; + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + src_buffer->n_pixels); + + for (size_t x = 0; x < x_limit; x++, dst_pixels += 4) { + dst_pixels[3] = 0xffff; + dst_pixels[2] = cpu_to_le16(in_pixels[x].r); + dst_pixels[1] = cpu_to_le16(in_pixels[x].g); + dst_pixels[0] = cpu_to_le16(in_pixels[x].b); + } +} + void *get_frame_to_line_function(u32 format) { switch (format) { @@ -137,6 +205,10 @@ void *get_frame_to_line_function(u32 format) return &ARGB8888_to_argb_u16; case DRM_FORMAT_XRGB8888: return &XRGB8888_to_argb_u16; + case DRM_FORMAT_ARGB16161616: + return &ARGB16161616_to_argb_u16; + case DRM_FORMAT_XRGB16161616: + return &XRGB16161616_to_argb_u16; default: return NULL; } @@ -149,6 +221,10 @@ void *get_line_to_frame_function(u32 format) return &argb_u16_to_ARGB8888; case DRM_FORMAT_XRGB8888: return &argb_u16_to_XRGB8888; + case DRM_FORMAT_ARGB16161616: + return &argb_u16_to_ARGB16161616; + case DRM_FORMAT_XRGB16161616: + return &argb_u16_to_XRGB16161616; default: return NULL; } diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index d5f3fbfc0f7c..f823fe315de6 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -13,11 +13,14 @@ static const u32 vkms_formats[] = { DRM_FORMAT_XRGB8888, + DRM_FORMAT_XRGB16161616 }; static const u32 vkms_plane_formats[] = { DRM_FORMAT_ARGB8888, - DRM_FORMAT_XRGB8888 + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XRGB16161616, + DRM_FORMAT_ARGB16161616 }; static struct drm_plane_state * diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 0ce5e28d260d..16feea884646 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -16,6 +16,8 @@ static const u32 vkms_wb_formats[] = { DRM_FORMAT_XRGB8888, + DRM_FORMAT_XRGB16161616, + DRM_FORMAT_ARGB16161616 }; static const struct drm_connector_funcs vkms_wb_connector_funcs = { From 396369d6754993e40f1c84b2e22e40e92dfa4c49 Mon Sep 17 00:00:00 2001 From: Igor Torrente <igormtorrente@gmail.com> Date: Mon, 5 Sep 2022 16:08:11 -0300 Subject: [PATCH 371/396] drm: vkms: Add support to the RGB565 format This commit also adds new helper macros to deal with fixed-point arithmetic. It was done to improve the precision of the conversion to ARGB16161616 since the "conversion ratio" is not an integer. V3: Adapt the handlers to the new format introduced in patch 7 V3. V5: Minor improvements V6: Minor improvements (Pekka Paalanen) Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-10-igormtorrente@gmail.com --- drivers/gpu/drm/vkms/vkms_formats.c | 70 +++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_plane.c | 6 ++- drivers/gpu/drm/vkms/vkms_writeback.c | 3 +- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 3af36476a7df..300abb4d1dfe 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -5,6 +5,23 @@ #include "vkms_formats.h" +/* The following macros help doing fixed point arithmetic. */ +/* + * With Fixed-Point scale 15 we have 17 and 15 bits of integer and fractional + * parts respectively. + * | 0000 0000 0000 0000 0.000 0000 0000 0000 | + * 31 0 + */ +#define SHIFT 15 + +#define INT_TO_FIXED(a) ((a) << SHIFT) +#define FIXED_MUL(a, b) ((s32)(((s64)(a) * (b)) >> SHIFT)) +#define FIXED_DIV(a, b) ((s32)(((s64)(a) << SHIFT) / (b))) +/* This macro converts a fixed point number to int, and round half up it */ +#define FIXED_TO_INT_ROUND(a) (((a) + (1 << (SHIFT - 1))) >> SHIFT) +#define INT_TO_FIXED_DIV(a, b) (FIXED_DIV(INT_TO_FIXED(a), INT_TO_FIXED(b))) +#define INT_TO_FIXED_DIV(a, b) (FIXED_DIV(INT_TO_FIXED(a), INT_TO_FIXED(b))) + static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int y) { return frame_info->offset + (y * frame_info->pitch) @@ -112,6 +129,30 @@ static void XRGB16161616_to_argb_u16(struct line_buffer *stage_buffer, } } +static void RGB565_to_argb_u16(struct line_buffer *stage_buffer, + const struct vkms_frame_info *frame_info, int y) +{ + struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; + u16 *src_pixels = get_packed_src_addr(frame_info, y); + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + stage_buffer->n_pixels); + + s32 fp_rb_ratio = INT_TO_FIXED_DIV(65535, 31); + s32 fp_g_ratio = INT_TO_FIXED_DIV(65535, 63); + + for (size_t x = 0; x < x_limit; x++, src_pixels++) { + u16 rgb_565 = le16_to_cpu(*src_pixels); + s32 fp_r = INT_TO_FIXED((rgb_565 >> 11) & 0x1f); + s32 fp_g = INT_TO_FIXED((rgb_565 >> 5) & 0x3f); + s32 fp_b = INT_TO_FIXED(rgb_565 & 0x1f); + + out_pixels[x].a = (u16)0xffff; + out_pixels[x].r = FIXED_TO_INT_ROUND(FIXED_MUL(fp_r, fp_rb_ratio)); + out_pixels[x].g = FIXED_TO_INT_ROUND(FIXED_MUL(fp_g, fp_g_ratio)); + out_pixels[x].b = FIXED_TO_INT_ROUND(FIXED_MUL(fp_b, fp_rb_ratio)); + } +} + /* * The following functions take an line of argb_u16 pixels from the * src_buffer, convert them to a specific format, and store them in the @@ -198,6 +239,31 @@ static void argb_u16_to_XRGB16161616(struct vkms_frame_info *frame_info, } } +static void argb_u16_to_RGB565(struct vkms_frame_info *frame_info, + const struct line_buffer *src_buffer, int y) +{ + int x_dst = frame_info->dst.x1; + u16 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y); + struct pixel_argb_u16 *in_pixels = src_buffer->pixels; + int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), + src_buffer->n_pixels); + + s32 fp_rb_ratio = INT_TO_FIXED_DIV(65535, 31); + s32 fp_g_ratio = INT_TO_FIXED_DIV(65535, 63); + + for (size_t x = 0; x < x_limit; x++, dst_pixels++) { + s32 fp_r = INT_TO_FIXED(in_pixels[x].r); + s32 fp_g = INT_TO_FIXED(in_pixels[x].g); + s32 fp_b = INT_TO_FIXED(in_pixels[x].b); + + u16 r = FIXED_TO_INT_ROUND(FIXED_DIV(fp_r, fp_rb_ratio)); + u16 g = FIXED_TO_INT_ROUND(FIXED_DIV(fp_g, fp_g_ratio)); + u16 b = FIXED_TO_INT_ROUND(FIXED_DIV(fp_b, fp_rb_ratio)); + + *dst_pixels = cpu_to_le16(r << 11 | g << 5 | b); + } +} + void *get_frame_to_line_function(u32 format) { switch (format) { @@ -209,6 +275,8 @@ void *get_frame_to_line_function(u32 format) return &ARGB16161616_to_argb_u16; case DRM_FORMAT_XRGB16161616: return &XRGB16161616_to_argb_u16; + case DRM_FORMAT_RGB565: + return &RGB565_to_argb_u16; default: return NULL; } @@ -225,6 +293,8 @@ void *get_line_to_frame_function(u32 format) return &argb_u16_to_ARGB16161616; case DRM_FORMAT_XRGB16161616: return &argb_u16_to_XRGB16161616; + case DRM_FORMAT_RGB565: + return &argb_u16_to_RGB565; default: return NULL; } diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index f823fe315de6..f4319066adcc 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -13,14 +13,16 @@ static const u32 vkms_formats[] = { DRM_FORMAT_XRGB8888, - DRM_FORMAT_XRGB16161616 + DRM_FORMAT_XRGB16161616, + DRM_FORMAT_RGB565 }; static const u32 vkms_plane_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB16161616, - DRM_FORMAT_ARGB16161616 + DRM_FORMAT_ARGB16161616, + DRM_FORMAT_RGB565 }; static struct drm_plane_state * diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 16feea884646..84a51cd281b9 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -17,7 +17,8 @@ static const u32 vkms_wb_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB16161616, - DRM_FORMAT_ARGB16161616 + DRM_FORMAT_ARGB16161616, + DRM_FORMAT_RGB565 }; static const struct drm_connector_funcs vkms_wb_connector_funcs = { From 8e3d857c70dd317cb71301d9b49f0506ce409a1e Mon Sep 17 00:00:00 2001 From: Xin Ji <xji@analogixsemi.com> Date: Sat, 3 Sep 2022 21:08:33 +0800 Subject: [PATCH 372/396] drm/bridge: anx7625: Set HPD irq detect window to 2ms Some panels trigger HPD irq due to noise, the HPD debounce may be 1.8ms, exceeding the default irq detect window, ~1.4ms. This patch set HPD irq detection window to 2ms to tolerate the HPD noise. Signed-off-by: Xin Ji <xji@analogixsemi.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220903130833.541463-1-xji@analogixsemi.com --- drivers/gpu/drm/bridge/analogix/anx7625.c | 14 ++++++++++++++ drivers/gpu/drm/bridge/analogix/anx7625.h | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index c74b5df4cade..0c323b5a1c99 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1440,6 +1440,20 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx) static int anx7625_read_hpd_status_p0(struct anx7625_data *ctx) { + int ret; + + /* Set irq detect window to 2ms */ + ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, + HPD_DET_TIMER_BIT0_7, HPD_TIME & 0xFF); + ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, + HPD_DET_TIMER_BIT8_15, + (HPD_TIME >> 8) & 0xFF); + ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, + HPD_DET_TIMER_BIT16_23, + (HPD_TIME >> 16) & 0xFF); + if (ret < 0) + return ret; + return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, SYSTEM_STSTUS); } diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h index e257a84db962..14f33d6be289 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.h +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h @@ -132,6 +132,12 @@ #define I2S_SLAVE_MODE 0x08 #define AUDIO_LAYOUT 0x01 +#define HPD_DET_TIMER_BIT0_7 0xea +#define HPD_DET_TIMER_BIT8_15 0xeb +#define HPD_DET_TIMER_BIT16_23 0xec +/* HPD debounce time 2ms for 27M clock */ +#define HPD_TIME 54000 + #define AUDIO_CONTROL_REGISTER 0xe6 #define TDM_TIMING_MODE 0x08 From f8ad757e40c9c776a13eaa56d73e8e62381517b6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Mon, 4 Apr 2022 14:30:40 -0700 Subject: [PATCH 373/396] drm/scheduler: quieten kernel-doc warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix kernel-doc warnings in gpu_scheduler.h and sched_main.c. Quashes these warnings: include/drm/gpu_scheduler.h:332: warning: missing initial short description on line: * struct drm_sched_backend_ops include/drm/gpu_scheduler.h:412: warning: missing initial short description on line: * struct drm_gpu_scheduler include/drm/gpu_scheduler.h:461: warning: Function parameter or member 'dev' not described in 'drm_gpu_scheduler' drivers/gpu/drm/scheduler/sched_main.c:201: warning: missing initial short description on line: * drm_sched_dependency_optimized drivers/gpu/drm/scheduler/sched_main.c:995: warning: Function parameter or member 'dev' not described in 'drm_sched_init' Fixes: 2d33948e4e00 ("drm/scheduler: add documentation") Fixes: 8ab62eda177b ("drm/sched: Add device pointer to drm_gpu_scheduler") Fixes: 542cff7893a3 ("drm/sched: Avoid lockdep spalt on killing a processes") Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Cc: Nayan Deshmukh <nayan26deshmukh@gmail.com> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Christian König <christian.koenig@amd.com> Cc: Jiawei Gu <Jiawei.Gu@amd.com> Cc: dri-devel@lists.freedesktop.org Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220404213040.12912-1-rdunlap@infradead.org --- drivers/gpu/drm/scheduler/sched_main.c | 3 ++- include/drm/gpu_scheduler.h | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index e0ab14e0fb6b..e5a4ecde0063 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -198,7 +198,7 @@ static void drm_sched_job_done_cb(struct dma_fence *f, struct dma_fence_cb *cb) } /** - * drm_sched_dependency_optimized + * drm_sched_dependency_optimized - test if the dependency can be optimized * * @fence: the dependency fence * @entity: the entity which depends on the above fence @@ -993,6 +993,7 @@ static int drm_sched_main(void *param) * used * @score: optional score atomic shared with other schedulers * @name: name used for debugging + * @dev: target &struct device * * Return 0 on success, otherwise error code. */ diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index addb135eeea6..599855c6a672 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -329,10 +329,10 @@ enum drm_gpu_sched_stat { }; /** - * struct drm_sched_backend_ops + * struct drm_sched_backend_ops - Define the backend operations + * called by the scheduler * - * Define the backend operations called by the scheduler, - * these functions should be implemented in driver side. + * These functions should be implemented in the driver side. */ struct drm_sched_backend_ops { /** @@ -409,7 +409,7 @@ struct drm_sched_backend_ops { }; /** - * struct drm_gpu_scheduler + * struct drm_gpu_scheduler - scheduler instance-specific data * * @ops: backend operations provided by the driver. * @hw_submission_limit: the max size of the hardware queue. @@ -435,6 +435,7 @@ struct drm_sched_backend_ops { * @_score: score used when the driver doesn't provide one * @ready: marks if the underlying HW is ready to work * @free_guilty: A hit to time out handler to free the guilty job. + * @dev: system &struct device * * One scheduler is implemented for each hardware ring. */ From 07d50b8222d0d6fcbb281393048e36e797334ac6 Mon Sep 17 00:00:00 2001 From: Douglas Anderson <dianders@chromium.org> Date: Wed, 20 Jul 2022 16:23:21 -0700 Subject: [PATCH 374/396] drm/panel-edp: Fix typo in kerneldoc comment (appers=>appears) Ever since I got the spell-check working in my editor this one has been bugging me. Fix it. Signed-off-by: Douglas Anderson <dianders@chromium.org> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220720162314.1.Ieef5bc3848df40b71605b70bb571d6429e8978de@changeid --- drivers/gpu/drm/panel/panel-edp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index a95db0cfa43c..1d357f90d457 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -53,7 +53,7 @@ struct panel_delay { * before the HPD signal is reliable. Ideally this is 0 but some panels, * board designs, or bad pulldown configs can cause a glitch here. * - * NOTE: on some old panel data this number appers to be much too big. + * NOTE: on some old panel data this number appears to be much too big. * Presumably some old panels simply didn't have HPD hooked up and put * the hpd_absent here because this field predates the * hpd_absent. While that works, it's non-ideal. From 5e1bfb277d3b87bc580735564eb487c0be3848b3 Mon Sep 17 00:00:00 2001 From: Alisa Khabibrakhmanova <khabibrakhmanova@ispras.ru> Date: Fri, 29 Jul 2022 12:06:43 +0300 Subject: [PATCH 375/396] drm/via: Add new condition to via_dma_cleanup() Pointer dev_priv->mmio, which was checked for NULL at via_do_init_map(), is passed to via_do_cleanup_map() and is dereferenced there without check. The patch adds the condition in via_dma_cleanup() which prevents potential NULL pointer dereference. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 22f579c621e2 ("drm: Add via unichrome support") Signed-off-by: Alisa Khabibrakhmanova <khabibrakhmanova@ispras.ru> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220729090643.240778-1-khabibrakhmanova@ispras.ru --- drivers/gpu/drm/via/via_dri1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c index f659c0c0465c..217d1e84b0ea 100644 --- a/drivers/gpu/drm/via/via_dri1.c +++ b/drivers/gpu/drm/via/via_dri1.c @@ -2961,7 +2961,7 @@ int via_dma_cleanup(struct drm_device *dev) drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - if (dev_priv->ring.virtual_start) { + if (dev_priv->ring.virtual_start && dev_priv->mmio) { via_cmdbuf_reset(dev_priv); drm_legacy_ioremapfree(&dev_priv->ring.map, dev); From e6643298aac0d9d77696513722c85d7808e4c84a Mon Sep 17 00:00:00 2001 From: Li zeming <zeming@nfschina.com> Date: Wed, 7 Sep 2022 11:29:34 +0800 Subject: [PATCH 376/396] drm/ttm: Remove unnecessary '0' values from ret MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable ret is assigned in the judgment branch statement, he does not need to initialize the assignment. Signed-off-by: Li zeming <zeming@nfschina.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220907032934.4490-1-zeming@nfschina.com Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> --- include/drm/ttm/ttm_bo_driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 897b88f0bd59..1afa891f488a 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -106,7 +106,7 @@ static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, bool interruptible, bool no_wait, struct ww_acquire_ctx *ticket) { - int ret = 0; + int ret; if (no_wait) { bool success; From 857dbf2431ba8abcd6f0f1335ea637580ebe5507 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:38 +0200 Subject: [PATCH 377/396] drm/vc4: vec: Remove empty mode_fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mode_fixup hooks are deprecated, and the behaviour we implement is the default one anyway. Let's remove it. Reviewed-by: Noralf Trønnes <noralf@tronnes.org> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-24-459522d653a7@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 4a788c1c9058..31c0de0ffdbb 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -483,14 +483,6 @@ err_dev_exit: drm_dev_exit(idx); } - -static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -518,7 +510,6 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { .disable = vc4_vec_encoder_disable, .enable = vc4_vec_encoder_enable, - .mode_fixup = vc4_vec_encoder_mode_fixup, .atomic_check = vc4_vec_encoder_atomic_check, .atomic_mode_set = vc4_vec_encoder_atomic_mode_set, }; From 336f29e0f8564e317e42b9eef6e2c17e838944f4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:39 +0200 Subject: [PATCH 378/396] drm/vc4: vec: Convert to atomic helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VC4 VEC driver still uses legacy enable and disable hook implementation. Let's convert to the atomic variants. Reviewed-by: Noralf Trønnes <noralf@tronnes.org> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-25-459522d653a7@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 31c0de0ffdbb..2c5d44e34f45 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -375,7 +375,8 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) return 0; } -static void vc4_vec_encoder_disable(struct drm_encoder *encoder) +static void vc4_vec_encoder_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); @@ -406,7 +407,8 @@ err_dev_exit: drm_dev_exit(idx); } -static void vc4_vec_encoder_enable(struct drm_encoder *encoder) +static void vc4_vec_encoder_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); @@ -508,9 +510,9 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, } static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { - .disable = vc4_vec_encoder_disable, - .enable = vc4_vec_encoder_enable, .atomic_check = vc4_vec_encoder_atomic_check, + .atomic_disable = vc4_vec_encoder_disable, + .atomic_enable = vc4_vec_encoder_enable, .atomic_mode_set = vc4_vec_encoder_atomic_mode_set, }; From 38baec94ca584b7370c78b0fc445ef5def269ac6 Mon Sep 17 00:00:00 2001 From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com> Date: Mon, 29 Aug 2022 15:11:40 +0200 Subject: [PATCH 379/396] drm/vc4: vec: Refactor VEC TV mode setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the mode_set function pointer logic to declarative config0, config1 and custom_freq fields, to make TV mode setting logic more concise and uniform. Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com> Reviewed-by: Noralf Trønnes <noralf@tronnes.org> [Maxime: Fixed != 0 check, added tv_mode variable] Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-26-459522d653a7@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 88 +++++++++-------------------------- 1 file changed, 23 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 2c5d44e34f45..f015cd4c53d0 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -194,7 +194,9 @@ enum vc4_vec_tv_mode_id { struct vc4_vec_tv_mode { const struct drm_display_mode *mode; - void (*mode_set)(struct vc4_vec *vec); + u32 config0; + u32 config1; + u32 custom_freq; }; static const struct debugfs_reg32 vec_regs[] = { @@ -224,34 +226,6 @@ static const struct debugfs_reg32 vec_regs[] = { VC4_REG32(VEC_DAC_MISC), }; -static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec) -{ - struct drm_device *drm = vec->connector.dev; - int idx; - - if (!drm_dev_enter(drm, &idx)) - return; - - VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN); - VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); - - drm_dev_exit(idx); -} - -static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec) -{ - struct drm_device *drm = vec->connector.dev; - int idx; - - if (!drm_dev_enter(drm, &idx)) - return; - - VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD); - VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); - - drm_dev_exit(idx); -} - static const struct drm_display_mode ntsc_mode = { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, @@ -259,37 +233,6 @@ static const struct drm_display_mode ntsc_mode = { DRM_MODE_FLAG_INTERLACE) }; -static void vc4_vec_pal_mode_set(struct vc4_vec *vec) -{ - struct drm_device *drm = vec->connector.dev; - int idx; - - if (!drm_dev_enter(drm, &idx)) - return; - - VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); - VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); - - drm_dev_exit(idx); -} - -static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec) -{ - struct drm_device *drm = vec->connector.dev; - int idx; - - if (!drm_dev_enter(drm, &idx)) - return; - - VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); - VEC_WRITE(VEC_CONFIG1, - VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ); - VEC_WRITE(VEC_FREQ3_2, 0x223b); - VEC_WRITE(VEC_FREQ1_0, 0x61d1); - - drm_dev_exit(idx); -} - static const struct drm_display_mode pal_mode = { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, @@ -300,19 +243,24 @@ static const struct drm_display_mode pal_mode = { static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { [VC4_VEC_TV_MODE_NTSC] = { .mode = &ntsc_mode, - .mode_set = vc4_vec_ntsc_mode_set, + .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, [VC4_VEC_TV_MODE_NTSC_J] = { .mode = &ntsc_mode, - .mode_set = vc4_vec_ntsc_j_mode_set, + .config0 = VEC_CONFIG0_NTSC_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, [VC4_VEC_TV_MODE_PAL] = { .mode = &pal_mode, - .mode_set = vc4_vec_pal_mode_set, + .config0 = VEC_CONFIG0_PAL_BDGHI_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, [VC4_VEC_TV_MODE_PAL_M] = { .mode = &pal_mode, - .mode_set = vc4_vec_pal_m_mode_set, + .config0 = VEC_CONFIG0_PAL_BDGHI_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, + .custom_freq = 0x223b61d1, }, }; @@ -412,6 +360,8 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder, { struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); + const struct vc4_vec_tv_mode *tv_mode = + vec->tv_mode; int idx, ret; if (!drm_dev_enter(drm, &idx)) @@ -470,7 +420,15 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder, /* Mask all interrupts. */ VEC_WRITE(VEC_MASK0, 0); - vec->tv_mode->mode_set(vec); + VEC_WRITE(VEC_CONFIG0, tv_mode->config0); + VEC_WRITE(VEC_CONFIG1, tv_mode->config1); + + if (tv_mode->custom_freq) { + VEC_WRITE(VEC_FREQ3_2, + (tv_mode->custom_freq >> 16) & 0xffff); + VEC_WRITE(VEC_FREQ1_0, + tv_mode->custom_freq & 0xffff); + } VEC_WRITE(VEC_DAC_MISC, VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N); From 296674b936b12837f94590812cfabc5aa4a9a950 Mon Sep 17 00:00:00 2001 From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com> Date: Mon, 29 Aug 2022 15:11:41 +0200 Subject: [PATCH 380/396] drm/vc4: vec: Remove redundant atomic_mode_set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's remove the superfluous tv_mode field, which was redundant with the mode field in struct drm_tv_connector_state. Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com> Reviewed-by: Noralf Trønnes <noralf@tronnes.org> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-27-459522d653a7@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index f015cd4c53d0..7eb1e34f12b5 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -171,8 +171,6 @@ struct vc4_vec { struct clk *clock; - const struct vc4_vec_tv_mode *tv_mode; - struct debugfs_regset32 regset; }; @@ -316,7 +314,6 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property, VC4_VEC_TV_MODE_NTSC); - vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC]; drm_connector_attach_encoder(connector, &vec->encoder.base); @@ -360,8 +357,11 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder, { struct drm_device *drm = encoder->dev; struct vc4_vec *vec = encoder_to_vc4_vec(encoder); + struct drm_connector *connector = &vec->connector; + struct drm_connector_state *conn_state = + drm_atomic_get_new_connector_state(state, connector); const struct vc4_vec_tv_mode *tv_mode = - vec->tv_mode; + &vc4_vec_tv_modes[conn_state->tv.mode]; int idx, ret; if (!drm_dev_enter(drm, &idx)) @@ -443,15 +443,6 @@ err_dev_exit: drm_dev_exit(idx); } -static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - struct vc4_vec *vec = encoder_to_vc4_vec(encoder); - - vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; -} - static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -471,7 +462,6 @@ static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { .atomic_check = vc4_vec_encoder_atomic_check, .atomic_disable = vc4_vec_encoder_disable, .atomic_enable = vc4_vec_encoder_enable, - .atomic_mode_set = vc4_vec_encoder_atomic_mode_set, }; static int vc4_vec_late_register(struct drm_encoder *encoder) From 30d7565be96b3946c18a1ce3fd538f7946839092 Mon Sep 17 00:00:00 2001 From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com> Date: Mon, 29 Aug 2022 15:11:42 +0200 Subject: [PATCH 381/396] drm/vc4: vec: Fix timings for VEC modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes vertical timings of the VEC (composite output) modes to accurately represent the 525-line ("NTSC") and 625-line ("PAL") ITU-R standards. Previous timings were actually defined as 502 and 601 lines, resulting in non-standard 62.69 Hz and 52 Hz signals being generated, respectively. Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com> Acked-by: Noralf Trønnes <noralf@tronnes.org> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-28-459522d653a7@cerno.tech --- drivers/gpu/drm/vc4/vc4_vec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 7eb1e34f12b5..0b3333865702 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -227,14 +227,14 @@ static const struct debugfs_reg32 vec_regs[] = { static const struct drm_display_mode ntsc_mode = { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, - 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0, + 480, 480 + 7, 480 + 7 + 6, 525, 0, DRM_MODE_FLAG_INTERLACE) }; static const struct drm_display_mode pal_mode = { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, - 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0, + 576, 576 + 4, 576 + 4 + 6, 625, 0, DRM_MODE_FLAG_INTERLACE) }; From fcb9229b72866f1af4630773d878dd67b3947f89 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:48 +0200 Subject: [PATCH 382/396] drm/sun4i: tv: Remove unused mode_valid The mode_valid implementation is pretty much a nop, let's remove it. Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-34-459522d653a7@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 94883abe0dfd..53152d77c392 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -497,16 +497,8 @@ static int sun4i_tv_comp_get_modes(struct drm_connector *connector) return i; } -static int sun4i_tv_comp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - /* TODO */ - return MODE_OK; -} - static const struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs = { .get_modes = sun4i_tv_comp_get_modes, - .mode_valid = sun4i_tv_comp_mode_valid, }; static void From 5233860da01038e0b4ce20bc68d871cb9caa7109 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:49 +0200 Subject: [PATCH 383/396] drm/sun4i: tv: Convert to atomic hooks The sun4i TV driver still uses legacy enable and disable hook implementation. Let's convert to the atomic variants. Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-35-459522d653a7@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 53152d77c392..f7aad995ab5b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -339,7 +339,8 @@ static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode, mode->vtotal = mode->vsync_end + tv_mode->vback_porch; } -static void sun4i_tv_disable(struct drm_encoder *encoder) +static void sun4i_tv_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); @@ -353,7 +354,8 @@ static void sun4i_tv_disable(struct drm_encoder *encoder) sunxi_engine_disable_color_correction(crtc->engine); } -static void sun4i_tv_enable(struct drm_encoder *encoder) +static void sun4i_tv_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); @@ -469,8 +471,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, } static const struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = { - .disable = sun4i_tv_disable, - .enable = sun4i_tv_enable, + .atomic_disable = sun4i_tv_disable, + .atomic_enable = sun4i_tv_enable, .mode_set = sun4i_tv_mode_set, }; From dcc22148673dbc02e33c220d9d6446005c9497c7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:51 +0200 Subject: [PATCH 384/396] drm/sun4i: tv: Remove useless function The drm_connector_to_sun4i_tv() function isn't used anywhere in the driver, so let's remove it. Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-37-459522d653a7@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index f7aad995ab5b..ccc5a6cccd6a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -275,13 +275,6 @@ drm_encoder_to_sun4i_tv(struct drm_encoder *encoder) encoder); } -static inline struct sun4i_tv * -drm_connector_to_sun4i_tv(struct drm_connector *connector) -{ - return container_of(connector, struct sun4i_tv, - connector); -} - /* * FIXME: If only the drm_display_mode private field was usable, this * could go away... From 18294b74db2fee99142f4ae027cf0c88eb544654 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:52 +0200 Subject: [PATCH 385/396] drm/sun4i: tv: Remove useless destroy function Our destroy implementation is just calling the generic helper, so let's just remove our function and directly use the helper. Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-38-459522d653a7@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index ccc5a6cccd6a..7823ac83fd68 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -496,15 +496,9 @@ static const struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_fu .get_modes = sun4i_tv_comp_get_modes, }; -static void -sun4i_tv_comp_connector_destroy(struct drm_connector *connector) -{ - drm_connector_cleanup(connector); -} - static const struct drm_connector_funcs sun4i_tv_comp_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = sun4i_tv_comp_connector_destroy, + .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, From 7c4180b151fca559d2bf1bf321f35ac8509fdc8c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:53 +0200 Subject: [PATCH 386/396] drm/sun4i: tv: Rename error label The other error labels in sun4i_tv_bind() are named after the task they perform (err_disable_clk to call clk_disable_unprepare for example). However, the err_cleanup_connector is named after the calling site (drm_connector_init failing) and will actually cleanup the encoder. Let's rename it to err_cleanup_encoder to be consistent. Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-39-459522d653a7@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 7823ac83fd68..d3bf8fb3f6db 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -585,7 +585,7 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, if (ret) { dev_err(dev, "Couldn't initialise the Composite connector\n"); - goto err_cleanup_connector; + goto err_cleanup_encoder; } tv->connector.interlace_allowed = true; @@ -593,7 +593,7 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, return 0; -err_cleanup_connector: +err_cleanup_encoder: drm_encoder_cleanup(&tv->encoder); err_disable_clk: clk_disable_unprepare(tv->clk); From fad08d6248f88c9420eff5471ad34978a5c6c805 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:54 +0200 Subject: [PATCH 387/396] drm/sun4i: tv: Add missing reset assertion The reset line is deasserted at bind, and asserted if we ever encounter an error there. However, it's never asserted in unbind which will lead to a resource unbalance. Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-40-459522d653a7@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index d3bf8fb3f6db..5965a0f72fc3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -610,6 +610,7 @@ static void sun4i_tv_unbind(struct device *dev, struct device *master, drm_connector_cleanup(&tv->connector); drm_encoder_cleanup(&tv->encoder); clk_disable_unprepare(tv->clk); + reset_control_assert(tv->reset); } static const struct component_ops sun4i_tv_ops = { From 85faca8ca0f659263b5fb2385e4c231cc075bd84 Mon Sep 17 00:00:00 2001 From: Chia-I Wu <olvaffe@gmail.com> Date: Wed, 31 Aug 2022 12:06:01 -0700 Subject: [PATCH 388/396] drm/virtio: set fb_modifiers_not_supported Without this, the drm core advertises LINEAR modifier which is incorrect. Also userspace virgl does not support modifiers. For example, it causes chrome on ozone/drm to fail with "Failed to create scanout buffer". Fixes: 2af104290da5 ("drm: introduce fb_modifiers_not_supported flag in mode_config") Suggested-by: Shao-Chuan Lee <shaochuan@chromium.org> Signed-off-by: Chia-I Wu <olvaffe@gmail.com> Link: http://patchwork.freedesktop.org/patch/msgid/20220831190601.1295129-1-olvaffe@gmail.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 5c7f198c0712..9ea7611a9e0f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -349,6 +349,8 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) vgdev->ddev->mode_config.max_width = XRES_MAX; vgdev->ddev->mode_config.max_height = YRES_MAX; + vgdev->ddev->mode_config.fb_modifiers_not_supported = true; + for (i = 0 ; i < vgdev->num_scanouts; ++i) vgdev_output_init(vgdev, i); From e740ceb53e4579a7a4063712cebecac3c343b189 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Tue, 6 Sep 2022 16:29:57 +0200 Subject: [PATCH 389/396] drm/bochs: fix blanking VGA_IS1_RC is the color mode register (VGA_IS1_RM the one for monochrome mode, note C vs. M at the end). So when using VGA_IS1_RC make sure the vga device is actually in color mode and set the corresponding bit in the misc register. Reproducible when booting VMs in UEFI mode with some edk2 versions (edk2 fix is on the way too). Doesn't happen in BIOS mode because in that case the vgabios already flips the bit. Fixes: 250e743915d4 ("drm/bochs: Add screen blanking support") Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Link: http://patchwork.freedesktop.org/patch/msgid/20220906142957.2763577-1-kraxel@redhat.com --- drivers/gpu/drm/tiny/bochs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c index 08de13774862..a51262289aef 100644 --- a/drivers/gpu/drm/tiny/bochs.c +++ b/drivers/gpu/drm/tiny/bochs.c @@ -309,6 +309,8 @@ static void bochs_hw_fini(struct drm_device *dev) static void bochs_hw_blank(struct bochs_device *bochs, bool blank) { DRM_DEBUG_DRIVER("hw_blank %d\n", blank); + /* enable color bit (so VGA_IS1_RC access works) */ + bochs_vga_writeb(bochs, VGA_MIS_W, VGA_MIS_COLOR); /* discard ar_flip_flop */ (void)bochs_vga_readb(bochs, VGA_IS1_RC); /* blank or unblank; we need only update index and set 0x20 */ From 4da7aad41c8f6fcccb37e2c95a07c84835effd7d Mon Sep 17 00:00:00 2001 From: Zongmin Zhou <zhouzongmin@kylinos.cn> Date: Wed, 7 Sep 2022 17:44:23 +0800 Subject: [PATCH 390/396] drm/qxl: fix the suspend/resume issue on qxl device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Details: Currently, when trying to suspend and resume with qxl device, there are some error messages after resuming, eventually caused to black screen and can't be recovered. The first error message: [ 64.668577][ C3] [drm] driver is in bug mode This error is due to guest qxl driver will call qxl_reinit_memslots(qdev) during system resume, but didn't call qxl_io_reset(qdev) before this, Then will cause the QXL_IO_MEMSLOT_ADD operation to fail on QEMU, qxl->guest_bug flag will be set,As a result, the QXL device can't communicate with guest qxl driver through the IO port. after fix the first error,can success to resume and login to desktop, but shortly after that will observe the second error message : [ 353.095343][ T863] qxl 0000:00:02.0: object_init failed for (262144, 0x00000001) [ 353.096660][ T863] [drm:qxl_gem_object_create [qxl]] *ERROR* Failed to allocate GEM object (260852, 1, 4096, -12) [ 353.097277][ T863] [drm:qxl_alloc_ioctl [qxl]] *ERROR* qxl_alloc_ioctl: failed to create gem ret=-12 [ 368.197538][ T863] qxl 0000:00:02.0: object_init failed for (3149824, 0x00000001) [ 368.197541][ T863] [drm:qxl_alloc_bo_reserved [qxl]] *ERROR* failed to allocate VRAM BO The problem is caused by calling qxl_ring_init_hdr(qdev->release_ring) in qxl_drm_resume() function. When do QXL_IO_RESET,QEMU will call init_qxl_ram(), so params like prod,cons,notify_on_cons and notify_on_prod will be set to default value. Ring push/pop actions for release_ring can be performed normally. But call qxl_ring_init_hdr(qdev->release_ring) will eventually set notify_on_prod to number of QXL_RELEASE_RING_SIZE, affect the value of notify in qxl_push_free_res() function always be false, QEMU will no longer send events of QXL_INTERRUPT_DISPLAY to the guest qxl driver,so qxl_ring_pop() will never been called anymore, and can't do dma_fence_signal(),result to ttm_bo_wait_ctx(bo, ctx) always return EBUSY,fail to call qxl_bo_create(). Test scenario: 1) start virtual machine with qemu command "-device qxl-vga" 2) click suspend botton to enter suspend mode 3) resume and observe the error message in kernel logs,screen will be black Let's fix this by reset io and remove the qxl_ring_init_hdr calling. Signed-off-by: Zongmin Zhou<zhouzongmin@kylinos.cn> Suggested-by: Ming Xie<xieming@kylinos.cn> Link: http://patchwork.freedesktop.org/patch/msgid/20220907094423.93581-1-min_halo@163.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/qxl/qxl_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 1cb6f0c224bb..3044ca948ce2 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -194,7 +194,6 @@ static int qxl_drm_resume(struct drm_device *dev, bool thaw) qdev->ram_header->int_mask = QXL_INTERRUPT_MASK; if (!thaw) { qxl_reinit_memslots(qdev); - qxl_ring_init_hdr(qdev->release_ring); } qxl_create_monitors_object(qdev); @@ -220,6 +219,7 @@ static int qxl_pm_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct qxl_device *qdev = to_qxl(drm_dev); pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); @@ -227,6 +227,7 @@ static int qxl_pm_resume(struct device *dev) return -EIO; } + qxl_io_reset(qdev); return qxl_drm_resume(drm_dev, false); } From 580c00e64f121ad2d99e6f43796a49ea2cb4439d Mon Sep 17 00:00:00 2001 From: Jilin Yuan <yuanjilin@cdjrlc.com> Date: Wed, 7 Sep 2022 19:39:27 +0800 Subject: [PATCH 391/396] drm/gma500: fix repeated words in comments Delete the redundant word 'for'. Signed-off-by: Jilin Yuan <yuanjilin@cdjrlc.com> Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220907113927.35305-1-yuanjilin@cdjrlc.com --- drivers/gpu/drm/gma500/oaktrail_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 6004390d647a..64761f46b434 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -310,7 +310,7 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) temp & ~PIPEACONF_ENABLE, i); REG_READ_WITH_AUX(map->conf, i); } - /* Wait for for the pipe disable to take effect. */ + /* Wait for the pipe disable to take effect. */ gma_wait_for_vblank(dev); temp = REG_READ_WITH_AUX(map->dpll, i); From 622113b9f11fdaeff2cc17f684fb7e4968fd8a4e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas <javierm@redhat.com> Date: Tue, 6 Sep 2022 00:27:59 +0200 Subject: [PATCH 392/396] drm/ssd130x: Replace simple display helpers with the atomic helpers The simple display pipeline is a set of helpers that can be used by DRM drivers to avoid dealing with all the needed components and just define a few functions to operate a simple display device with one full-screen scanout buffer feeding a single output. But it is arguable that this provides the correct level of abstraction for simple drivers, and recently some have been ported from using these simple display helpers to use the regular atomic helpers instead. The rationale for this is that the simple display pipeline helpers don't hide that much of the DRM complexity, while adding an indirection layer that conflates the concepts of CRTCs and planes. This makes the helpers less flexible and harder to be reused among different graphics drivers. Also, for simple drivers, using the full atomic helpers doesn't require a lot of additional code. So adding a simple display pipeline layer may not be worth it. For these reasons, let's follow that trend and make ssd130x a plain DRM driver that creates its own primary plane, CRTC, enconder and connector. Suggested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20220905222759.2597186-1-javierm@redhat.com --- drivers/gpu/drm/solomon/ssd130x.c | 292 ++++++++++++++++++++---------- drivers/gpu/drm/solomon/ssd130x.h | 9 +- 2 files changed, 205 insertions(+), 96 deletions(-) diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index f87f5443e714..79e8e2017c68 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -18,6 +18,7 @@ #include <linux/pwm.h> #include <linux/regulator/consumer.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_edid.h> @@ -564,94 +565,32 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_m return ret; } -static int ssd130x_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +static int ssd130x_primary_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *new_state) { - struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane); + struct drm_crtc *new_crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = NULL; - if (mode->hdisplay != ssd130x->mode.hdisplay && - mode->vdisplay != ssd130x->mode.vdisplay) - return MODE_ONE_SIZE; + if (new_crtc) + new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc); - if (mode->hdisplay != ssd130x->mode.hdisplay) - return MODE_ONE_WIDTH; - - if (mode->vdisplay != ssd130x->mode.vdisplay) - return MODE_ONE_HEIGHT; - - return MODE_OK; + return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); } -static void ssd130x_display_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void ssd130x_primary_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *old_state) { - struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev); + struct drm_plane_state *plane_state = plane->state; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - struct drm_device *drm = &ssd130x->drm; - int idx, ret; - - ret = ssd130x_power_on(ssd130x); - if (ret) - return; - - ret = ssd130x_init(ssd130x); - if (ret) - goto out_power_off; - - if (!drm_dev_enter(drm, &idx)) - goto out_power_off; - - ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &plane_state->dst); - - ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON); - - backlight_enable(ssd130x->bl_dev); - - drm_dev_exit(idx); - - return; -out_power_off: - ssd130x_power_off(ssd130x); -} - -static void ssd130x_display_pipe_disable(struct drm_simple_display_pipe *pipe) -{ - struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev); - struct drm_device *drm = &ssd130x->drm; - int idx; - - if (!drm_dev_enter(drm, &idx)) - return; - - ssd130x_clear_screen(ssd130x); - - backlight_disable(ssd130x->bl_dev); - - ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF); - - ssd130x_power_off(ssd130x); - - drm_dev_exit(idx); -} - -static void ssd130x_display_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_plane_state) -{ - struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev); - struct drm_plane_state *plane_state = pipe->plane.state; - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - struct drm_framebuffer *fb = plane_state->fb; - struct drm_device *drm = &ssd130x->drm; + struct drm_device *drm = plane->dev; struct drm_rect src_clip, dst_clip; int idx; - if (!fb) - return; - - if (!pipe->crtc.state->active) - return; - if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip)) return; @@ -667,15 +606,132 @@ static void ssd130x_display_pipe_update(struct drm_simple_display_pipe *pipe, drm_dev_exit(idx); } -static const struct drm_simple_display_pipe_funcs ssd130x_pipe_funcs = { - .mode_valid = ssd130x_display_pipe_mode_valid, - .enable = ssd130x_display_pipe_enable, - .disable = ssd130x_display_pipe_disable, - .update = ssd130x_display_pipe_update, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, +static void ssd130x_primary_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *old_state) +{ + struct drm_device *drm = plane->dev; + struct ssd130x_device *ssd130x = drm_to_ssd130x(drm); + int idx; + + if (!drm_dev_enter(drm, &idx)) + return; + + ssd130x_clear_screen(ssd130x); + + drm_dev_exit(idx); +} + +static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = ssd130x_primary_plane_helper_atomic_check, + .atomic_update = ssd130x_primary_plane_helper_atomic_update, + .atomic_disable = ssd130x_primary_plane_helper_atomic_disable, }; -static int ssd130x_connector_get_modes(struct drm_connector *connector) +static const struct drm_plane_funcs ssd130x_primary_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +static enum drm_mode_status ssd130x_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) +{ + struct ssd130x_device *ssd130x = drm_to_ssd130x(crtc->dev); + + if (mode->hdisplay != ssd130x->mode.hdisplay && + mode->vdisplay != ssd130x->mode.vdisplay) + return MODE_ONE_SIZE; + else if (mode->hdisplay != ssd130x->mode.hdisplay) + return MODE_ONE_WIDTH; + else if (mode->vdisplay != ssd130x->mode.vdisplay) + return MODE_ONE_HEIGHT; + + return MODE_OK; +} + +static int ssd130x_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *new_state) +{ + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + int ret; + + ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false); + if (ret) + return ret; + + return drm_atomic_add_affected_planes(new_state, crtc); +} + +/* + * The CRTC is always enabled. Screen updates are performed by + * the primary plane's atomic_update function. Disabling clears + * the screen in the primary plane's atomic_disable function. + */ +static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = { + .mode_valid = ssd130x_crtc_helper_mode_valid, + .atomic_check = ssd130x_crtc_helper_atomic_check, +}; + +static void ssd130x_crtc_reset(struct drm_crtc *crtc) +{ + struct drm_device *drm = crtc->dev; + struct ssd130x_device *ssd130x = drm_to_ssd130x(drm); + + ssd130x_init(ssd130x); + + drm_atomic_helper_crtc_reset(crtc); +} + +static const struct drm_crtc_funcs ssd130x_crtc_funcs = { + .reset = ssd130x_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static void ssd130x_encoder_helper_atomic_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) +{ + struct drm_device *drm = encoder->dev; + struct ssd130x_device *ssd130x = drm_to_ssd130x(drm); + int ret; + + ret = ssd130x_power_on(ssd130x); + if (ret) + return; + + ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON); + + backlight_enable(ssd130x->bl_dev); +} + +static void ssd130x_encoder_helper_atomic_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) +{ + struct drm_device *drm = encoder->dev; + struct ssd130x_device *ssd130x = drm_to_ssd130x(drm); + + backlight_disable(ssd130x->bl_dev); + + ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF); + + ssd130x_power_off(ssd130x); +} + +static const struct drm_encoder_helper_funcs ssd130x_encoder_helper_funcs = { + .atomic_enable = ssd130x_encoder_helper_atomic_enable, + .atomic_disable = ssd130x_encoder_helper_atomic_disable, +}; + +static const struct drm_encoder_funcs ssd130x_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static int ssd130x_connector_helper_get_modes(struct drm_connector *connector) { struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev); struct drm_display_mode *mode; @@ -695,7 +751,7 @@ static int ssd130x_connector_get_modes(struct drm_connector *connector) } static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = { - .get_modes = ssd130x_connector_get_modes, + .get_modes = ssd130x_connector_helper_get_modes, }; static const struct drm_connector_funcs ssd130x_connector_funcs = { @@ -806,8 +862,16 @@ static int ssd130x_init_modeset(struct ssd130x_device *ssd130x) struct device *dev = ssd130x->dev; struct drm_device *drm = &ssd130x->drm; unsigned long max_width, max_height; + struct drm_plane *primary_plane; + struct drm_crtc *crtc; + struct drm_encoder *encoder; + struct drm_connector *connector; int ret; + /* + * Modesetting + */ + ret = drmm_mode_config_init(drm); if (ret) { dev_err(dev, "DRM mode config init failed: %d\n", ret); @@ -833,25 +897,65 @@ static int ssd130x_init_modeset(struct ssd130x_device *ssd130x) drm->mode_config.preferred_depth = 32; drm->mode_config.funcs = &ssd130x_mode_config_funcs; - ret = drm_connector_init(drm, &ssd130x->connector, &ssd130x_connector_funcs, + /* Primary plane */ + + primary_plane = &ssd130x->primary_plane; + ret = drm_universal_plane_init(drm, primary_plane, 0, &ssd130x_primary_plane_funcs, + ssd130x_formats, ARRAY_SIZE(ssd130x_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) { + dev_err(dev, "DRM primary plane init failed: %d\n", ret); + return ret; + } + + drm_plane_helper_add(primary_plane, &ssd130x_primary_plane_helper_funcs); + + drm_plane_enable_fb_damage_clips(primary_plane); + + /* CRTC */ + + crtc = &ssd130x->crtc; + ret = drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, + &ssd130x_crtc_funcs, NULL); + if (ret) { + dev_err(dev, "DRM crtc init failed: %d\n", ret); + return ret; + } + + drm_crtc_helper_add(crtc, &ssd130x_crtc_helper_funcs); + + /* Encoder */ + + encoder = &ssd130x->encoder; + ret = drm_encoder_init(drm, encoder, &ssd130x_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) { + dev_err(dev, "DRM encoder init failed: %d\n", ret); + return ret; + } + + drm_encoder_helper_add(encoder, &ssd130x_encoder_helper_funcs); + + encoder->possible_crtcs = drm_crtc_mask(crtc); + + /* Connector */ + + connector = &ssd130x->connector; + ret = drm_connector_init(drm, connector, &ssd130x_connector_funcs, DRM_MODE_CONNECTOR_Unknown); if (ret) { dev_err(dev, "DRM connector init failed: %d\n", ret); return ret; } - drm_connector_helper_add(&ssd130x->connector, &ssd130x_connector_helper_funcs); + drm_connector_helper_add(connector, &ssd130x_connector_helper_funcs); - ret = drm_simple_display_pipe_init(drm, &ssd130x->pipe, &ssd130x_pipe_funcs, - ssd130x_formats, ARRAY_SIZE(ssd130x_formats), - NULL, &ssd130x->connector); + ret = drm_connector_attach_encoder(connector, encoder); if (ret) { - dev_err(dev, "DRM simple display pipeline init failed: %d\n", ret); + dev_err(dev, "DRM attach connector to encoder failed: %d\n", ret); return ret; } - drm_plane_enable_fb_damage_clips(&ssd130x->pipe.plane); - drm_mode_config_reset(drm); return 0; diff --git a/drivers/gpu/drm/solomon/ssd130x.h b/drivers/gpu/drm/solomon/ssd130x.h index 4c4a84e962e7..03038c1b6476 100644 --- a/drivers/gpu/drm/solomon/ssd130x.h +++ b/drivers/gpu/drm/solomon/ssd130x.h @@ -13,8 +13,11 @@ #ifndef __SSD1307X_H__ #define __SSD1307X_H__ +#include <drm/drm_connector.h> +#include <drm/drm_crtc.h> #include <drm/drm_drv.h> -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_encoder.h> +#include <drm/drm_plane_helper.h> #include <linux/regmap.h> @@ -42,8 +45,10 @@ struct ssd130x_deviceinfo { struct ssd130x_device { struct drm_device drm; struct device *dev; - struct drm_simple_display_pipe pipe; struct drm_display_mode mode; + struct drm_plane primary_plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector connector; struct i2c_client *client; From ec491291dc94914cf962dcd399c3e9b43b00a770 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Mon, 29 Aug 2022 15:11:50 +0200 Subject: [PATCH 393/396] drm/sun4i: tv: Merge mode_set into atomic_enable Our mode_set implementation can be merged into our atomic_enable implementation to simplify things, so let's do this. Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-36-459522d653a7@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tv.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 5965a0f72fc3..74ff5ad6a8b9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -352,23 +352,13 @@ static void sun4i_tv_enable(struct drm_encoder *encoder, { struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); + struct drm_crtc_state *crtc_state = + drm_atomic_get_new_crtc_state(state, encoder->crtc); + struct drm_display_mode *mode = &crtc_state->mode; + const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); DRM_DEBUG_DRIVER("Enabling the TV Output\n"); - sunxi_engine_apply_color_correction(crtc->engine); - - regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, - SUN4I_TVE_EN_ENABLE, - SUN4I_TVE_EN_ENABLE); -} - -static void sun4i_tv_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); - const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); - /* Enable and map the DAC to the output */ regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, SUN4I_TVE_EN_DAC_MAP_MASK, @@ -461,12 +451,17 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, SUN4I_TVE_RESYNC_FIELD : 0)); regmap_write(tv->regs, SUN4I_TVE_SLAVE_REG, 0); + + sunxi_engine_apply_color_correction(crtc->engine); + + regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, + SUN4I_TVE_EN_ENABLE, + SUN4I_TVE_EN_ENABLE); } static const struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = { .atomic_disable = sun4i_tv_disable, .atomic_enable = sun4i_tv_enable, - .mode_set = sun4i_tv_mode_set, }; static int sun4i_tv_comp_get_modes(struct drm_connector *connector) From 758d7b3483b6eae4e0d52dc18ed6b4ed8fc1330e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai <wenst@chromium.org> Date: Thu, 8 Sep 2022 16:54:54 +0800 Subject: [PATCH 394/396] drm/panel-edp: Add Innolux N120ACA-EA1 panel entry This panel has the same delay timing as N116BCA-EA1 from the same company, which is also the same as delay_200_500_e80_d50. Add an entry for it. Signed-off-by: Chen-Yu Tsai <wenst@chromium.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220908085454.1024167-2-wenst@chromium.org --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 1d357f90d457..4dfcc0758e06 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1889,6 +1889,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"), + EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"), EDP_PANEL_ENTRY('I', 'V', 'O', 0x057d, &delay_200_500_e200, "R140NWF5 RH"), EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "M133NW4J-R3"), From 5d832b6694e094b176627ed9918a1b21c56fb742 Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@intel.com> Date: Wed, 7 Sep 2022 17:25:42 +0300 Subject: [PATCH 395/396] drm/dp_mst: Avoid deleting payloads for connectors staying enabled When an MST connector stays enabled during a commit the connector's MST state needs to be added to the atomic state, but the corresponding MST payload allocation shouldn't be set for deletion; fix such modesets by ensuring the above even if the connector was already enabled before the modeset. The issue led to the following: [ 761.992923] i915 0000:00:02.0: drm_WARN_ON(payload->delete) [ 761.992949] WARNING: CPU: 6 PID: 1401 at drivers/gpu/drm/display/drm_dp_mst_topology.c:4221 drm_dp_atomic_find_time_slots+0x236/0x280 [drm_display_helper] [ 761.992955] Modules linked in: snd_hda_intel i915 drm_buddy drm_display_helper drm_kms_helper ttm drm snd_hda_codec_hdmi snd_intel_dspcfg snd_hda_codec snd_hwdep snd_hda_core snd_pcm prime_numbers i2c_algo_bit syscopyarea sysfillrect sysimgblt fb_sys_fops x86_pkg_temp_thermal cdc_ether coretemp crct10dif_pclmul usbnet crc32_pclmul mii ghash_clmulni_intel e1000e mei_me ptp i2c_i801 pps_core mei i2c_smbus intel_lpss_pci fuse [last unloaded: drm] [ 761.992986] CPU: 6 PID: 1401 Comm: testdisplay Tainted: G U 6.0.0-rc4-imre+ #565 [ 761.992989] Hardware name: Intel Corporation Alder Lake Client Platform/AlderLake-P DDR5 RVP, BIOS ADLPFWI1.R00.3135.A00.2203251419 03/25/2022 [ 761.992990] RIP: 0010:drm_dp_atomic_find_time_slots+0x236/0x280 [drm_display_helper] [ 761.992994] Code: 4c 8b 67 50 4d 85 e4 75 03 4c 8b 27 e8 03 28 4e e1 48 c7 c1 8b 26 2c a0 4c 89 e2 48 c7 c7 a8 26 2c a0 48 89 c6 e8 31 d5 88 e1 <0f> 0b 49 8b 85 d0 00 00 00 4c 89 fa 48 c7 c6 a0 41 2c a0 48 8b 78 [ 761.992995] RSP: 0018:ffffc9000177ba60 EFLAGS: 00010286 [ 761.992998] RAX: 0000000000000000 RBX: ffff88810d2f1540 RCX: 0000000000000000 [ 761.992999] RDX: 0000000000000001 RSI: ffffffff82368a25 RDI: 00000000ffffffff [ 761.993000] RBP: ffff888142299d80 R08: ffff8884adbfdfe8 R09: 00000000ffefffff [ 761.993001] R10: ffff8884a6bfe000 R11: ffff8884ac443c30 R12: ffff888102972f90 [ 761.993002] R13: ffff8881163e2cf0 R14: 00000000000003ac R15: ffff88810c501000 [ 761.993003] FS: 00007f81e4c459c0(0000) GS:ffff888496500000(0000) knlGS:0000000000000000 [ 761.993004] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 761.993005] CR2: 0000555dac962a98 CR3: 0000000123a34006 CR4: 0000000000770ee0 [ 761.993006] PKRU: 55555554 [ 761.993007] Call Trace: [ 761.993009] <TASK> [ 761.993012] intel_dp_mst_compute_config+0x19a/0x350 [i915] [ 761.993090] intel_atomic_check+0xf37/0x3180 [i915] [ 761.993168] drm_atomic_check_only+0x5d3/0xa60 [drm] [ 761.993182] drm_atomic_commit+0x56/0xc0 [drm] [ 761.993192] ? drm_plane_get_damage_clips.cold+0x1c/0x1c [drm] [ 761.993204] drm_atomic_helper_set_config+0x78/0xc0 [drm_kms_helper] [ 761.993214] drm_mode_setcrtc+0x1ed/0x750 [drm] [ 761.993232] ? drm_mode_getcrtc+0x180/0x180 [drm] [ 761.993241] drm_ioctl_kernel+0xb5/0x150 [drm] [ 761.993252] drm_ioctl+0x203/0x3d0 [drm] [ 761.993261] ? drm_mode_getcrtc+0x180/0x180 [drm] [ 761.993276] __x64_sys_ioctl+0x8a/0xb0 [ 761.993281] do_syscall_64+0x38/0x90 [ 761.993285] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 761.993287] RIP: 0033:0x7f81e551aaff [ 761.993288] Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <41> 89 c0 3d 00 f0 ff ff 77 1f 48 8b 44 24 18 64 48 2b 04 25 28 00 [ 761.993290] RSP: 002b:00007fff4304af10 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 761.993292] RAX: ffffffffffffffda RBX: 00007fff4304afa0 RCX: 00007f81e551aaff [ 761.993293] RDX: 00007fff4304afa0 RSI: 00000000c06864a2 RDI: 0000000000000004 [ 761.993294] RBP: 00000000c06864a2 R08: 0000000000000000 R09: 0000555dac8a9c68 [ 761.993294] R10: 0000000000000000 R11: 0000000000000246 R12: 00000000000008c4 [ 761.993295] R13: 0000000000000004 R14: 0000555dac8a9c68 R15: 00007fff4304b098 [ 761.993301] </TASK> Fixes: 083351e96386 ("drm/display/dp_mst: Fix modeset tracking in drm_dp_atomic_release_vcpi_slots()") Testcase: igt@testdisplay Cc: Lyude Paul <lyude@redhat.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220907142542.1681994-1-imre.deak@intel.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 1de438151cc3..4442cc5602d4 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4322,6 +4322,9 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, return -EINVAL; } + if (new_conn_state->crtc) + return 0; + drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots); if (!payload->delete) { drm_dp_mst_put_port_malloc(port); From 89b03aeaef16f8ab48c10c399f97c836bdbae838 Mon Sep 17 00:00:00 2001 From: Melissa Wen <mwen@igalia.com> Date: Sat, 10 Sep 2022 18:03:03 -0100 Subject: [PATCH 396/396] drm/vkms: fix 32bit compilation error by replacing macros Replace vkms_formats macro for fixed-point operations with functions from drm/drm_fixed.h to do the same job and fix 32-bit compilation errors. v2: - don't cast results to s32 (Igor) - add missing drm_fixp2int conversion (Igor) Fixes: a19c2ac9858 ("drm: vkms: Add support to the RGB565 format") Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> (v1) Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1) Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220910190303.682897-1-mwen@igalia.com --- drivers/gpu/drm/vkms/vkms_formats.c | 53 +++++++++++------------------ 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 300abb4d1dfe..d4950688b3f1 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -1,27 +1,12 @@ // SPDX-License-Identifier: GPL-2.0+ -#include <drm/drm_rect.h> +#include <linux/kernel.h> #include <linux/minmax.h> +#include <drm/drm_rect.h> +#include <drm/drm_fixed.h> #include "vkms_formats.h" -/* The following macros help doing fixed point arithmetic. */ -/* - * With Fixed-Point scale 15 we have 17 and 15 bits of integer and fractional - * parts respectively. - * | 0000 0000 0000 0000 0.000 0000 0000 0000 | - * 31 0 - */ -#define SHIFT 15 - -#define INT_TO_FIXED(a) ((a) << SHIFT) -#define FIXED_MUL(a, b) ((s32)(((s64)(a) * (b)) >> SHIFT)) -#define FIXED_DIV(a, b) ((s32)(((s64)(a) << SHIFT) / (b))) -/* This macro converts a fixed point number to int, and round half up it */ -#define FIXED_TO_INT_ROUND(a) (((a) + (1 << (SHIFT - 1))) >> SHIFT) -#define INT_TO_FIXED_DIV(a, b) (FIXED_DIV(INT_TO_FIXED(a), INT_TO_FIXED(b))) -#define INT_TO_FIXED_DIV(a, b) (FIXED_DIV(INT_TO_FIXED(a), INT_TO_FIXED(b))) - static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int y) { return frame_info->offset + (y * frame_info->pitch) @@ -137,19 +122,19 @@ static void RGB565_to_argb_u16(struct line_buffer *stage_buffer, int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), stage_buffer->n_pixels); - s32 fp_rb_ratio = INT_TO_FIXED_DIV(65535, 31); - s32 fp_g_ratio = INT_TO_FIXED_DIV(65535, 63); + s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31)); + s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63)); for (size_t x = 0; x < x_limit; x++, src_pixels++) { u16 rgb_565 = le16_to_cpu(*src_pixels); - s32 fp_r = INT_TO_FIXED((rgb_565 >> 11) & 0x1f); - s32 fp_g = INT_TO_FIXED((rgb_565 >> 5) & 0x3f); - s32 fp_b = INT_TO_FIXED(rgb_565 & 0x1f); + s64 fp_r = drm_int2fixp((rgb_565 >> 11) & 0x1f); + s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f); + s64 fp_b = drm_int2fixp(rgb_565 & 0x1f); out_pixels[x].a = (u16)0xffff; - out_pixels[x].r = FIXED_TO_INT_ROUND(FIXED_MUL(fp_r, fp_rb_ratio)); - out_pixels[x].g = FIXED_TO_INT_ROUND(FIXED_MUL(fp_g, fp_g_ratio)); - out_pixels[x].b = FIXED_TO_INT_ROUND(FIXED_MUL(fp_b, fp_rb_ratio)); + out_pixels[x].r = drm_fixp2int(drm_fixp_mul(fp_r, fp_rb_ratio)); + out_pixels[x].g = drm_fixp2int(drm_fixp_mul(fp_g, fp_g_ratio)); + out_pixels[x].b = drm_fixp2int(drm_fixp_mul(fp_b, fp_rb_ratio)); } } @@ -248,17 +233,17 @@ static void argb_u16_to_RGB565(struct vkms_frame_info *frame_info, int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), src_buffer->n_pixels); - s32 fp_rb_ratio = INT_TO_FIXED_DIV(65535, 31); - s32 fp_g_ratio = INT_TO_FIXED_DIV(65535, 63); + s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31)); + s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63)); for (size_t x = 0; x < x_limit; x++, dst_pixels++) { - s32 fp_r = INT_TO_FIXED(in_pixels[x].r); - s32 fp_g = INT_TO_FIXED(in_pixels[x].g); - s32 fp_b = INT_TO_FIXED(in_pixels[x].b); + s64 fp_r = drm_int2fixp(in_pixels[x].r); + s64 fp_g = drm_int2fixp(in_pixels[x].g); + s64 fp_b = drm_int2fixp(in_pixels[x].b); - u16 r = FIXED_TO_INT_ROUND(FIXED_DIV(fp_r, fp_rb_ratio)); - u16 g = FIXED_TO_INT_ROUND(FIXED_DIV(fp_g, fp_g_ratio)); - u16 b = FIXED_TO_INT_ROUND(FIXED_DIV(fp_b, fp_rb_ratio)); + u16 r = drm_fixp2int(drm_fixp_div(fp_r, fp_rb_ratio)); + u16 g = drm_fixp2int(drm_fixp_div(fp_g, fp_g_ratio)); + u16 b = drm_fixp2int(drm_fixp_div(fp_b, fp_rb_ratio)); *dst_pixels = cpu_to_le16(r << 11 | g << 5 | b); }