From 96b5d2e807f667320c66f41ddc1c473023a73ab2 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 20 Dec 2024 09:29:40 +0200 Subject: drm: xlnx: zynqmp_dpsub: Fix kernel doc Fix two kernel doc warnings introduced by the recent DP audio patch: - Add a doc line for the new "audio" field - Remove a reference to zynqmp_dpsub.c from zynqmp.rst, as the .c file no longer has structured comments Fixes: 3ec5c1579305 ("drm: xlnx: zynqmp_dpsub: Add DP audio support") Closes: https://lore.kernel.org/all/20241220154208.720d990b@canb.auug.org.au/ Reviewed-by: Vishal Sagar Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20241220-xilinx-dp-audio-doc-fix-v1-1-cc488996e463@ideasonboard.com --- drivers/gpu/drm/xlnx/zynqmp_dpsub.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h index 49875529c2a4..d771b8b199e0 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h @@ -60,6 +60,7 @@ struct zynqmp_dpsub_audio; * @layers: Video and graphics layers * @dp: The DisplayPort controller * @dma_align: DMA alignment constraint (must be a power of 2) + * @audio: DP audio data */ struct zynqmp_dpsub { struct device *dev; -- cgit v1.2.3-59-g8ed1b From 3f60dbd40d3f7aca312d1aa1131e204eb97a68b3 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 31 Dec 2024 17:44:17 +0800 Subject: drm/rockchip: dw_hdmi_qp: Add platform ctrl callback There are some control bits for IO and interrupts status scattered across different GRF on differt SOC. Add platform callback for this IO setting and interrupts status handling. Signed-off-by: Andy Yan Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20241231094425.253398-2-andyshrk@163.com --- drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 79 +++++++++++++++++--------- 1 file changed, 51 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c index e498767a0a66..4c82b8400b41 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c @@ -62,6 +62,12 @@ struct rockchip_hdmi_qp { int port_id; }; +struct rockchip_hdmi_qp_ctrl_ops { + void (*io_init)(struct rockchip_hdmi_qp *hdmi); + irqreturn_t (*irq_callback)(int irq, void *dev_id); + irqreturn_t (*hardirq_callback)(int irq, void *dev_id); +}; + static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder) { struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); @@ -226,9 +232,44 @@ static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static void dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp *hdmi) +{ + u32 val; + + val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | + HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | + HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | + HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); + regmap_write(hdmi->vo_regmap, + hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3, + val); + + val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, RK3588_SET_HPD_PATH_MASK); + regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); + + if (hdmi->port_id) + val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, RK3588_HDMI1_GRANT_SEL); + else + val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, RK3588_HDMI0_GRANT_SEL); + regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val); + + if (hdmi->port_id) + val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK); + else + val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK); + regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); +} + +static const struct rockchip_hdmi_qp_ctrl_ops rk3588_hdmi_ctrl_ops = { + .io_init = dw_hdmi_qp_rk3588_io_init, + .irq_callback = dw_hdmi_qp_rk3588_irq, + .hardirq_callback = dw_hdmi_qp_rk3588_hardirq, +}; + struct rockchip_hdmi_qp_cfg { unsigned int num_ports; unsigned int port_ids[MAX_HDMI_PORT_NUM]; + const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops; const struct dw_hdmi_qp_phy_ops *phy_ops; }; @@ -238,6 +279,7 @@ static const struct rockchip_hdmi_qp_cfg rk3588_hdmi_cfg = { 0xfde80000, 0xfdea0000, }, + .ctrl_ops = &rk3588_hdmi_ctrl_ops, .phy_ops = &rk3588_hdmi_phy_ops, }; @@ -261,7 +303,6 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, struct resource *res; struct clk_bulk_data *clks; int ret, irq, i; - u32 val; if (!pdev->dev.of_node) return -ENODEV; @@ -278,6 +319,12 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, if (!cfg) return -ENODEV; + if (!cfg->ctrl_ops || !cfg->ctrl_ops->io_init || + !cfg->ctrl_ops->irq_callback || !cfg->ctrl_ops->hardirq_callback) { + dev_err(dev, "Missing platform ctrl ops\n"); + return -ENODEV; + } + hdmi->dev = &pdev->dev; hdmi->port_id = -ENODEV; @@ -357,31 +404,7 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, return ret; } - val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | - HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | - HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | - HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); - regmap_write(hdmi->vo_regmap, - hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3, - val); - - val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, - RK3588_SET_HPD_PATH_MASK); - regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); - - if (hdmi->port_id) - val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, - RK3588_HDMI1_GRANT_SEL); - else - val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, - RK3588_HDMI0_GRANT_SEL); - regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val); - - if (hdmi->port_id) - val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK); - else - val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK); - regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); + cfg->ctrl_ops->io_init(hdmi); INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_qp_rk3588_hpd_work); @@ -394,8 +417,8 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, return irq; ret = devm_request_threaded_irq(hdmi->dev, irq, - dw_hdmi_qp_rk3588_hardirq, - dw_hdmi_qp_rk3588_irq, + cfg->ctrl_ops->hardirq_callback, + cfg->ctrl_ops->irq_callback, IRQF_SHARED, "dw-hdmi-qp-hpd", hdmi); if (ret) -- cgit v1.2.3-59-g8ed1b From 36439120efbdc62e2f47053e7ddfcc4e34364640 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 31 Dec 2024 17:44:19 +0800 Subject: drm/rockchip: dw_hdmi_qp: Add basic RK3576 HDMI output support The HDMI on RK3576 shares the same IP block (PHY and Controller) with rk3588. However, there are some control bits scattered in different GRF. Signed-off-by: Andy Yan Tested-by: Detlev Casanova Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20241231094425.253398-4-andyshrk@163.com --- drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 142 ++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c index 4c82b8400b41..9916843a6ff3 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c @@ -25,6 +25,41 @@ #include "rockchip_drm_drv.h" +#define RK3576_IOC_MISC_CON0 0xa400 +#define RK3576_HDMI_HPD_INT_MSK BIT(2) +#define RK3576_HDMI_HPD_INT_CLR BIT(1) + +#define RK3576_IOC_HDMI_HPD_STATUS 0xa440 +#define RK3576_HDMI_LEVEL_INT BIT(3) + +#define RK3576_VO0_GRF_SOC_CON1 0x0004 +#define RK3576_HDMI_FRL_MOD BIT(0) +#define RK3576_HDMI_HDCP14_MEM_EN BIT(15) + +#define RK3576_VO0_GRF_SOC_CON8 0x0020 +#define RK3576_COLOR_FORMAT_MASK (0xf << 4) +#define RK3576_COLOR_DEPTH_MASK (0xf << 8) +#define RK3576_RGB (0 << 4) +#define RK3576_YUV422 (0x1 << 4) +#define RK3576_YUV444 (0x2 << 4) +#define RK3576_YUV420 (0x3 << 4) +#define RK3576_8BPC (0x0 << 8) +#define RK3576_10BPC (0x6 << 8) +#define RK3576_CECIN_MASK BIT(3) + +#define RK3576_VO0_GRF_SOC_CON12 0x0030 +#define RK3576_GRF_OSDA_DLYN (0xf << 12) +#define RK3576_GRF_OSDA_DIV (0x7f << 1) +#define RK3576_GRF_OSDA_DLY_EN BIT(0) + +#define RK3576_VO0_GRF_SOC_CON14 0x0038 +#define RK3576_I2S_SEL_MASK BIT(0) +#define RK3576_SPDIF_SEL_MASK BIT(1) +#define HDCP0_P1_GPIO_IN BIT(2) +#define RK3576_SCLIN_MASK BIT(4) +#define RK3576_SDAIN_MASK BIT(5) +#define RK3576_HDMI_GRANT_SEL BIT(6) + #define RK3588_GRF_SOC_CON2 0x0308 #define RK3588_HDMI0_HPD_INT_MSK BIT(13) #define RK3588_HDMI0_HPD_INT_CLR BIT(12) @@ -167,6 +202,37 @@ static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = { .setup_hpd = dw_hdmi_qp_rk3588_setup_hpd, }; +static enum drm_connector_status +dw_hdmi_qp_rk3576_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) +{ + struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; + u32 val; + + regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &val); + + return val & RK3576_HDMI_LEVEL_INT ? + connector_status_connected : connector_status_disconnected; +} + +static void dw_hdmi_qp_rk3576_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) +{ + struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; + u32 val; + + val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_CLR, + RK3576_HDMI_HPD_INT_CLR | RK3576_HDMI_HPD_INT_MSK); + + regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); + regmap_write(hdmi->regmap, 0xa404, 0xffff0102); +} + +static const struct dw_hdmi_qp_phy_ops rk3576_hdmi_phy_ops = { + .init = dw_hdmi_qp_rk3588_phy_init, + .disable = dw_hdmi_qp_rk3588_phy_disable, + .read_hpd = dw_hdmi_qp_rk3576_read_hpd, + .setup_hpd = dw_hdmi_qp_rk3576_setup_hpd, +}; + static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work) { struct rockchip_hdmi_qp *hdmi = container_of(work, @@ -182,6 +248,43 @@ static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work) } } +static irqreturn_t dw_hdmi_qp_rk3576_hardirq(int irq, void *dev_id) +{ + struct rockchip_hdmi_qp *hdmi = dev_id; + u32 intr_stat, val; + + regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat); + if (intr_stat) { + val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_MSK, RK3576_HDMI_HPD_INT_MSK); + + regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); + return IRQ_WAKE_THREAD; + } + + return IRQ_NONE; +} + +static irqreturn_t dw_hdmi_qp_rk3576_irq(int irq, void *dev_id) +{ + struct rockchip_hdmi_qp *hdmi = dev_id; + u32 intr_stat, val; + + regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat); + + if (!intr_stat) + return IRQ_NONE; + + val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_CLR, RK3576_HDMI_HPD_INT_CLR); + regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); + mod_delayed_work(system_wq, &hdmi->hpd_work, + msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); + + val = HIWORD_UPDATE(0, RK3576_HDMI_HPD_INT_MSK); + regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); + + return IRQ_HANDLED; +} + static irqreturn_t dw_hdmi_qp_rk3588_hardirq(int irq, void *dev_id) { struct rockchip_hdmi_qp *hdmi = dev_id; @@ -232,6 +335,21 @@ static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static void dw_hdmi_qp_rk3576_io_init(struct rockchip_hdmi_qp *hdmi) +{ + u32 val; + + val = HIWORD_UPDATE(RK3576_SCLIN_MASK, RK3576_SCLIN_MASK) | + HIWORD_UPDATE(RK3576_SDAIN_MASK, RK3576_SDAIN_MASK) | + HIWORD_UPDATE(RK3576_HDMI_GRANT_SEL, RK3576_HDMI_GRANT_SEL) | + HIWORD_UPDATE(RK3576_I2S_SEL_MASK, RK3576_I2S_SEL_MASK); + + regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON14, val); + + val = HIWORD_UPDATE(0, RK3576_HDMI_HPD_INT_MSK); + regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); +} + static void dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp *hdmi) { u32 val; @@ -260,6 +378,12 @@ static void dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp *hdmi) regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); } +static const struct rockchip_hdmi_qp_ctrl_ops rk3576_hdmi_ctrl_ops = { + .io_init = dw_hdmi_qp_rk3576_io_init, + .irq_callback = dw_hdmi_qp_rk3576_irq, + .hardirq_callback = dw_hdmi_qp_rk3576_hardirq, +}; + static const struct rockchip_hdmi_qp_ctrl_ops rk3588_hdmi_ctrl_ops = { .io_init = dw_hdmi_qp_rk3588_io_init, .irq_callback = dw_hdmi_qp_rk3588_irq, @@ -273,6 +397,15 @@ struct rockchip_hdmi_qp_cfg { const struct dw_hdmi_qp_phy_ops *phy_ops; }; +static const struct rockchip_hdmi_qp_cfg rk3576_hdmi_cfg = { + .num_ports = 1, + .port_ids = { + 0x27da0000, + }, + .ctrl_ops = &rk3576_hdmi_ctrl_ops, + .phy_ops = &rk3576_hdmi_phy_ops, +}; + static const struct rockchip_hdmi_qp_cfg rk3588_hdmi_cfg = { .num_ports = 2, .port_ids = { @@ -284,8 +417,13 @@ static const struct rockchip_hdmi_qp_cfg rk3588_hdmi_cfg = { }; static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = { - { .compatible = "rockchip,rk3588-dw-hdmi-qp", - .data = &rk3588_hdmi_cfg }, + { + .compatible = "rockchip,rk3576-dw-hdmi-qp", + .data = &rk3576_hdmi_cfg + }, { + .compatible = "rockchip,rk3588-dw-hdmi-qp", + .data = &rk3588_hdmi_cfg + }, {}, }; MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids); -- cgit v1.2.3-59-g8ed1b From 69c0d83f0eeac6d0d573790c768fcbc902f0dfc5 Mon Sep 17 00:00:00 2001 From: Vignesh Raman Date: Tue, 17 Dec 2024 21:36:52 +0530 Subject: drm/ci: uprev IGT Uprev IGT to the latest version and update expectation files. Signed-off-by: Vignesh Raman Reviewed-by: Dmitry Baryshkov # msm Signed-off-by: Helen Koike Link: https://patchwork.freedesktop.org/patch/msgid/20241217160655.2371138-1-vignesh.raman@collabora.com --- drivers/gpu/drm/ci/gitlab-ci.yml | 2 +- drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt | 8 +- drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt | 21 +- drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt | 5 + drivers/gpu/drm/ci/xfails/i915-amly-fails.txt | 20 +- drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt | 14 + drivers/gpu/drm/ci/xfails/i915-amly-skips.txt | 1 + drivers/gpu/drm/ci/xfails/i915-apl-fails.txt | 8 +- drivers/gpu/drm/ci/xfails/i915-cml-fails.txt | 22 +- drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt | 7 + drivers/gpu/drm/ci/xfails/i915-cml-skips.txt | 1 + drivers/gpu/drm/ci/xfails/i915-glk-fails.txt | 31 +- drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt | 7 + drivers/gpu/drm/ci/xfails/i915-glk-skips.txt | 298 +++++++++++ drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt | 18 +- drivers/gpu/drm/ci/xfails/i915-jsl-flakes.txt | 15 +- drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt | 112 +++++ drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt | 55 +-- drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt | 13 + drivers/gpu/drm/ci/xfails/i915-whl-fails.txt | 15 +- drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt | 7 + .../gpu/drm/ci/xfails/mediatek-mt8173-fails.txt | 7 +- .../gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt | 7 + .../gpu/drm/ci/xfails/mediatek-mt8173-skips.txt | 5 + .../gpu/drm/ci/xfails/mediatek-mt8183-fails.txt | 12 +- .../gpu/drm/ci/xfails/mediatek-mt8183-skips.txt | 5 + drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt | 3 + .../xfails/msm-sc7180-trogdor-kingoftown-fails.txt | 1 - .../msm-sc7180-trogdor-kingoftown-flakes.txt | 14 + .../xfails/msm-sc7180-trogdor-kingoftown-skips.txt | 5 + .../msm-sc7180-trogdor-lazor-limozeen-fails.txt | 1 - .../msm-sc7180-trogdor-lazor-limozeen-skips.txt | 5 + drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt | 2 - drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt | 5 + drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt | 5 - .../gpu/drm/ci/xfails/rockchip-rk3288-fails.txt | 26 +- .../gpu/drm/ci/xfails/rockchip-rk3399-fails.txt | 13 +- .../gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt | 56 +++ .../gpu/drm/ci/xfails/rockchip-rk3399-skips.txt | 5 + .../gpu/drm/ci/xfails/virtio_gpu-none-skips.txt | 5 + drivers/gpu/drm/ci/xfails/vkms-none-fails.txt | 8 - drivers/gpu/drm/ci/xfails/vkms-none-skips.txt | 543 ++++++++++++++++++++- 42 files changed, 1202 insertions(+), 211 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml index 90bde9f00cc3..b7214718723c 100644 --- a/drivers/gpu/drm/ci/gitlab-ci.yml +++ b/drivers/gpu/drm/ci/gitlab-ci.yml @@ -5,7 +5,7 @@ variables: UPSTREAM_REPO: https://gitlab.freedesktop.org/drm/kernel.git TARGET_BRANCH: drm-next - IGT_VERSION: a73311079a5d8ac99eb25336a8369a2c3c6b519b + IGT_VERSION: 33adea9ebafd059ac88a5ccfec60536394f36c7c DEQP_RUNNER_GIT_URL: https://gitlab.freedesktop.org/mesa/deqp-runner.git DEQP_RUNNER_GIT_TAG: v0.20.0 diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt index f44dbce3151a..75374085f40f 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt @@ -14,10 +14,16 @@ amdgpu/amd_plane@mpo-scale-nv12,Fail amdgpu/amd_plane@mpo-scale-p010,Fail amdgpu/amd_plane@mpo-scale-rgb,Crash amdgpu/amd_plane@mpo-swizzle-toggle,Fail -amdgpu/amd_uvd_dec@amdgpu_uvd_decode,Fail +amdgpu/amd_uvd_dec@amdgpu_uvd_decode,Crash kms_addfb_basic@bad-pitch-65536,Fail kms_addfb_basic@bo-too-small,Fail kms_addfb_basic@too-high,Fail +kms_async_flips@alternate-sync-async-flip,Fail +kms_async_flips@alternate-sync-async-flip-atomic,Fail +kms_async_flips@test-cursor,Fail +kms_async_flips@test-cursor-atomic,Fail +kms_async_flips@test-time-stamp,Fail +kms_async_flips@test-time-stamp-atomic,Fail kms_atomic_transition@plane-all-modeset-transition-internal-panels,Fail kms_atomic_transition@plane-all-transition,Fail kms_atomic_transition@plane-all-transition-nonblocking,Fail diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt index e70bd9d447ca..adffb011298a 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt @@ -1,10 +1,3 @@ -# Board Name: hp-11A-G6-EE-grunt -# Bug Report: https://lore.kernel.org/amd-gfx/3542730f-b8d7-404d-a947-b7a5e95d661c@collabora.com/T/#u -# Failure Rate: 50 -# IGT Version: 1.28-g0df7b9b97 -# Linux Version: 6.9.0-rc7 -kms_async_flips@async-flip-with-page-flip-events - # Board Name: hp-11A-G6-EE-grunt # Bug Report: https://lore.kernel.org/amd-gfx/3542730f-b8d7-404d-a947-b7a5e95d661c@collabora.com/T/#u # Failure Rate: 50 @@ -25,3 +18,17 @@ kms_plane@pixel-format-source-clamping # IGT Version: 1.28-ga73311079 # Linux Version: 6.11.0-rc2 kms_async_flips@async-flip-with-page-flip-events + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://gitlab.freedesktop.org/drm/amd/-/issues/3835 +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_async_flips@async-flip-with-page-flip-events-atomic + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://gitlab.freedesktop.org/drm/amd/-/issues/3836 +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_async_flips@crc-atomic diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt index f41b3e112976..3879c4812a22 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt @@ -32,3 +32,8 @@ amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_exported_bo amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_exported_fence amdgpu/amd_vrr_range@freesync-parsing device_reset.* + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt index 0907cb0f6d9e..a29cea4f234c 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt @@ -1,16 +1,14 @@ core_setmaster@master-drop-set-shared-fd,Fail -core_setmaster@master-drop-set-user,Fail -core_setmaster_vs_auth,Fail i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail i915_module_load@resize-bar,Fail i915_pm_rpm@gem-execbuf-stress,Timeout i915_pm_rpm@module-reload,Fail -kms_cursor_legacy@short-flip-before-cursor-atomic-transitions,Timeout -kms_fb_coherency@memset-crc,Crash -kms_flip@busy-flip,Timeout -kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible,Fail +kms_async_flips@test-time-stamp,Timeout +kms_ccs@crc-sprite-planes-basic-y-tiled-ccs,Timeout +kms_flip@dpms-off-confusion-interruptible,Timeout +kms_flip@wf_vblank-ts-check-interruptible,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -33,20 +31,12 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail -kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu,Timeout kms_lease@lease-uevent,Fail +kms_lease@page-flip-implicit-plane,Timeout kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout -kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout -kms_pm_rpm@modeset-stress-extra-wait,Timeout -kms_pm_rpm@universal-planes,Timeout -kms_pm_rpm@universal-planes-dpms,Timeout -kms_prop_blob@invalid-set-prop,Fail -kms_rotation_crc@primary-rotation-180,Timeout -kms_vblank@query-forked-hang,Timeout perf@i915-ref-count,Fail perf_pmu@module-unload,Fail perf_pmu@rc6,Crash diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt index 0207c9807bee..fee246c25b9a 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt @@ -53,3 +53,17 @@ kms_pm_rpm@modeset-lpsp-stress # IGT Version: 1.28-ga73311079 # Linux Version: 6.11.0-rc2 kms_pm_rpm@drm-resources-equal + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13346 +# Failure Rate: 60 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +i915_hangman@gt-engine-error + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13345 +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +gen9_exec_parse@unaligned-access diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt index 5186ba3dbbc6..2ef1dc35a7fa 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt @@ -20,6 +20,7 @@ i915_pm_rc6_residency.* i915_suspend.* kms_scaling_modes.* i915_pm_rpm.* +i915_module_load@reload-with-fault-injection # Kernel panic drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt index 64772fedaed5..ee11999e3da1 100644 --- a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt @@ -1,3 +1,4 @@ +core_setmaster@master-drop-set-user,Fail i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail @@ -8,13 +9,13 @@ kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail +kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail @@ -29,13 +30,10 @@ kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail kms_pm_backlight@basic-brightness,Fail +kms_pm_backlight@brightness-with-dpms,Crash kms_pm_backlight@fade,Fail kms_pm_backlight@fade-with-dpms,Fail -kms_pm_rpm@legacy-planes,Timeout -kms_pm_rpm@legacy-planes-dpms,Timeout kms_pm_rpm@modeset-stress-extra-wait,Timeout -kms_pm_rpm@universal-planes,Timeout -kms_pm_rpm@universal-planes-dpms,Timeout kms_sysfs_edid_timing,Fail perf@i915-ref-count,Fail perf@non-zero-reason,Timeout diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt index f352b719cf7d..47b3f1d42bb6 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt @@ -1,5 +1,4 @@ core_setmaster@master-drop-set-shared-fd,Fail -core_setmaster@master-drop-set-user,Fail i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail @@ -9,9 +8,8 @@ i915_pipe_stress@stress-xrgb8888-ytiled,Fail i915_pm_rpm@gem-execbuf-stress,Timeout i915_pm_rpm@module-reload,Fail i915_pm_rpm@system-suspend-execbuf,Timeout -i915_pm_rps@engine-order,Fail -kms_big_fb@linear-16bpp-rotate-180,Timeout -kms_fb_coherency@memset-crc,Crash +kms_async_flips@test-time-stamp,Timeout +kms_ccs@crc-sprite-planes-basic-y-tiled-ccs,Timeout kms_flip@busy-flip,Timeout kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail @@ -36,25 +34,29 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail kms_lease@lease-uevent,Fail +kms_lease@page-flip-implicit-plane,Timeout kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout -kms_pm_rpm@modeset-stress-extra-wait,Timeout -kms_pm_rpm@universal-planes,Timeout -kms_pm_rpm@universal-planes-dpms,Timeout kms_psr2_sf@cursor-plane-update-sf,Fail kms_psr2_sf@overlay-plane-update-continuous-sf,Fail kms_psr2_sf@overlay-plane-update-sf-dmg-area,Fail kms_psr2_sf@overlay-primary-update-sf-dmg-area,Fail kms_psr2_sf@plane-move-sf-dmg-area,Fail +kms_psr2_sf@pr-cursor-plane-update-sf,Timeout kms_psr2_sf@primary-plane-update-sf-dmg-area,Fail kms_psr2_sf@primary-plane-update-sf-dmg-area-big-fb,Fail +kms_psr2_sf@psr2-cursor-plane-update-sf,Fail +kms_psr2_sf@psr2-overlay-plane-update-continuous-sf,Fail +kms_psr2_sf@psr2-overlay-plane-update-sf-dmg-area,Fail +kms_psr2_sf@psr2-overlay-primary-update-sf-dmg-area,Fail +kms_psr2_sf@psr2-plane-move-sf-dmg-area,Fail +kms_psr2_sf@psr2-primary-plane-update-sf-dmg-area,Fail +kms_psr2_sf@psr2-primary-plane-update-sf-dmg-area-big-fb,Fail kms_psr2_su@page_flip-NV12,Fail -kms_rotation_crc@primary-rotation-180,Timeout +kms_psr2_su@page_flip-P010,Fail kms_setmode@basic,Fail -kms_vblank@query-forked-hang,Timeout perf@i915-ref-count,Fail perf_pmu@module-unload,Fail perf_pmu@rc6,Crash diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt index d8401251e5f4..5343cc1c8696 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt @@ -25,3 +25,10 @@ kms_plane_alpha_blend@constant-alpha-min # IGT Version: 1.28-ga73311079 # Linux Version: 6.11.0-rc2 kms_async_flips@crc + +# Board Name: asus-C436FA-Flip-hatch +# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13347 +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +gen9_exec_parse@unaligned-access diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt index 9d753d97c9ab..c87ff8b40e99 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt @@ -20,6 +20,7 @@ xe_module_load.* api_intel_allocator.* kms_cursor_legacy.* i915_pm_rpm.* +kms_flip.* # Kernel panic drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt index 6eb64c672f7d..843c363b42f5 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt @@ -1,61 +1,35 @@ +core_setmaster@master-drop-set-shared-fd,Fail core_setmaster@master-drop-set-user,Fail -core_setmaster_vs_auth,Fail +gen9_exec_parse@unaligned-access,Fail i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail i915_module_load@resize-bar,Fail -kms_cursor_legacy@short-flip-before-cursor-atomic-transitions,Timeout kms_dirtyfb@default-dirtyfb-ioctl,Fail kms_dirtyfb@drrs-dirtyfb-ioctl,Fail kms_dirtyfb@fbc-dirtyfb-ioctl,Fail -kms_flip@blocking-wf_vblank,Fail -kms_flip@busy-flip,Timeout -kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible,Fail -kms_flip@wf_vblank-ts-check,Fail kms_flip@wf_vblank-ts-check-interruptible,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail -kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu,Timeout -kms_frontbuffer_tracking@fbc-tiling-linear,Fail kms_frontbuffer_tracking@fbcdrrs-tiling-linear,Fail kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail -kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout -kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout -kms_pm_rpm@legacy-planes,Timeout -kms_pm_rpm@legacy-planes-dpms,Timeout -kms_pm_rpm@modeset-stress-extra-wait,Timeout -kms_pm_rpm@universal-planes,Timeout -kms_pm_rpm@universal-planes-dpms,Timeout -kms_prop_blob@invalid-set-prop,Fail -kms_rotation_crc@multiplane-rotation,Fail -kms_rotation_crc@multiplane-rotation-cropping-bottom,Fail kms_rotation_crc@multiplane-rotation-cropping-top,Fail -kms_rotation_crc@primary-rotation-180,Timeout -kms_vblank@query-forked-hang,Timeout perf@non-zero-reason,Timeout sysfs_heartbeat_interval@long,Timeout -sysfs_heartbeat_interval@off,Timeout sysfs_preempt_timeout@off,Timeout sysfs_timeslice_duration@off,Timeout xe_module_load@force-load,Fail @@ -63,4 +37,3 @@ xe_module_load@load,Fail xe_module_load@many-reload,Fail xe_module_load@reload,Fail xe_module_load@reload-no-display,Fail -core_setmaster@master-drop-set-shared-fd,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt index 077886b76093..2a909c657343 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt @@ -11,3 +11,10 @@ core_hotunplug@unplug-rescan # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 kms_fb_coherency@memset-crc + +# Board Name: hp-x360-12b-ca0010nr-n4020-octopus +# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13348 +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_flip@dpms-off-confusion-interruptible diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt index 9c64146aed90..219ae839323a 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt @@ -27,3 +27,301 @@ perf.* # Kernel panic drm_fdinfo.* kms_plane_alpha_blend.* + +kms_async_flips.* +# [IGT] kms_async_flips: executing +# ------------[ cut here ]------------ +# i915 0000:00:02.0: [drm] drm_WARN_ON(intel_dp->pps.vdd_wakeref) +# WARNING: CPU: 0 PID: 1253 at drivers/gpu/drm/i915/display/intel_pps.c:760 intel_pps_vdd_on_unlocked+0x351/0x360 +# Modules linked in: +# CPU: 0 UID: 0 PID: 1253 Comm: kms_async_flips Tainted: G W 6.13.0-rc2-ge95c88d68ac3 #1 +# Tainted: [W]=WARN +# Hardware name: HP Bloog/Bloog, BIOS 09/19/2019 +# RIP: 0010:intel_pps_vdd_on_unlocked+0x351/0x360 +# Code: 8b 77 50 4d 85 f6 75 03 4c 8b 37 e8 19 98 03 00 48 c7 c1 10 d3 61 84 4c 89 f2 48 c7 c7 67 56 69 84 48 89 c6 e8 a0 22 63 ff 90 <0f> 0b 90 90 e9 5f fd ff ff e8 81 94 69 00 90 90 90 90 90 90 90 90 +# RSP: 0018:ffff9573c0dcfad8 EFLAGS: 00010286 +# RAX: 0000000000000000 RBX: ffff93498148e238 RCX: 00000000ffffdfff +# RDX: 0000000000000000 RSI: ffff9573c0dcf988 RDI: 0000000000000001 +# RBP: ffff934980d80000 R08: 0000000000009ffb R09: 00000000ffffdfff +# R10: 00000000ffffdfff R11: ffffffff8488c8a0 R12: ffff934980d80d68 +# R13: 0000000000000000 R14: ffff93498093c9b0 R15: 0000000000000000 +# FS: 00007fbf1f4486c0(0000) GS:ffff9349fbc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000055f260419028 CR3: 0000000106594000 CR4: 0000000000350ef0 +# Call Trace: +# +# intel_pps_vdd_on+0x78/0x150 +# intel_dp_detect+0xb9/0x7c0 +# drm_helper_probe_detect+0x47/0xb0 +# drm_helper_probe_single_connector_modes+0x40b/0x660 +# drm_mode_getconnector+0x369/0x490 +# drm_ioctl_kernel+0xad/0x110 +# drm_ioctl+0x235/0x4b0 +# __x64_sys_ioctl+0x8f/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7fbf208e4cdb +# 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 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 +# RSP: 002b:00007ffe061f6c60 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fbf208e4cdb +# RDX: 00007ffe061f6d00 RSI: 00000000c05064a7 RDI: 0000000000000003 +# RBP: 00007ffe061f6d00 R08: 0000000000000007 R09: 000055f260410cb0 +# R10: 650094cf40322201 R11: 0000000000000246 R12: 00000000c05064a7 +# R13: 0000000000000003 R14: 00000000c05064a7 R15: 00007ffe061f6d00 +# +# irq event stamp: 0 +# hardirqs last enabled at (0): [<0000000000000000>] 0x0 +# hardirqs last disabled at (0): [] copy_process+0xaf3/0x2eb0 +# softirqs last enabled at (0): [] copy_process+0xaf3/0x2eb0 +# softirqs last disabled at (0): [<0000000000000000>] 0x0 +# ---[ end trace 0000000000000000 ]--- +# i915 0000:00:02.0: [drm] *ERROR* PPS state mismatch +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* Failed to read DPCD register 0x92 +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# [IGT] kms_async_flips: starting subtest test-time-stamp +# i915 0000:00:02.0: [drm] *ERROR* [CRTC:70:pipe A] flip_done timed out +# i915 0000:00:02.0: [drm] *ERROR* flip_done timed out +# i915 0000:00:02.0: [drm] *ERROR* [CRTC:70:pipe A] commit wait timed out +# INFO: task kms_async_flips:1253 blocked for more than 122 seconds. +# Tainted: G W 6.13.0-rc2-ge95c88d68ac3 #1 +# "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +# task:kms_async_flips state:D stack:12720 pid:1253 tgid:1253 ppid:164 flags:0x00004006 +# Call Trace: +# +# __schedule+0x495/0xd20 +# schedule+0x35/0x120 +# drm_vblank_work_flush+0x91/0xf0 +# intel_wait_for_vblank_workers+0x58/0x90 +# intel_atomic_commit_tail+0xa86/0x15f0 +# intel_atomic_commit+0x257/0x2a0 +# drm_atomic_commit+0xac/0xe0 +# set_property_atomic+0x91/0x160 +# drm_mode_obj_set_property_ioctl+0xc1/0x110 +# drm_ioctl_kernel+0xad/0x110 +# drm_ioctl+0x235/0x4b0 +# __x64_sys_ioctl+0x8f/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7fbf208e4cdb +# RSP: 002b:00007ffe061f6c50 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 000055f24e272330 RCX: 00007fbf208e4cdb +# RDX: 00007ffe061f6ce0 RSI: 00000000c01864ba RDI: 0000000000000003 +# RBP: 00007ffe061f6ce0 R08: 0000000000000000 R09: 000055f2604184f0 +# R10: 00007fbf209ca310 R11: 0000000000000246 R12: 00000000c01864ba +# R13: 0000000000000003 R14: 0000000000000000 R15: 000055f26040ab90 +# +# INFO: lockdep is turned off. + +kms_lease.* +# [IGT] kms_lease: executing +# ------------[ cut here ]------------ +# i915 0000:00:02.0: [drm] drm_WARN_ON(intel_dp->pps.vdd_wakeref) +# WARNING: CPU: 1 PID: 1271 at drivers/gpu/drm/i915/display/intel_pps.c:760 intel_pps_vdd_on_unlocked+0x351/0x360 +# Modules linked in: +# CPU: 1 UID: 0 PID: 1271 Comm: kms_lease Tainted: G W 6.13.0-rc2-gfb6fd142a8eb #1 +# Tainted: [W]=WARN +# Hardware name: HP Bloog/Bloog, BIOS 09/19/2019 +# RIP: 0010:intel_pps_vdd_on_unlocked+0x351/0x360 +# Code: 8b 77 50 4d 85 f6 75 03 4c 8b 37 e8 19 98 03 00 48 c7 c1 10 d3 61 a1 4c 89 f2 48 c7 c7 67 56 69 a1 48 89 c6 e8 a0 22 63 ff 90 <0f> 0b 90 90 e9 5f fd ff ff e8 81 94 69 00 90 90 90 90 90 90 90 90 +# RSP: 0018:ffffb26500ddfad8 EFLAGS: 00010286 +# RAX: 0000000000000000 RBX: ffff988580dc6238 RCX: 00000000ffffdfff +# RDX: 0000000000000000 RSI: ffffb26500ddf988 RDI: 0000000000000001 +# RBP: ffff988580d90000 R08: 0000000000009ffb R09: 00000000ffffdfff +# R10: 00000000ffffdfff R11: ffffffffa188c8a0 R12: ffff988580d90d68 +# R13: 0000000000000000 R14: ffff98858093c9b0 R15: 0000000000000000 +# FS: 00007f6b0c60d6c0(0000) GS:ffff9885fbd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000055eea27460a8 CR3: 0000000105ac6000 CR4: 0000000000350ef0 +# Call Trace: +# +# intel_pps_vdd_on+0x78/0x150 +# intel_dp_detect+0xb9/0x7c0 +# drm_helper_probe_detect+0x47/0xb0 +# drm_helper_probe_single_connector_modes+0x40b/0x660 +# drm_mode_getconnector+0x369/0x490 +# drm_ioctl_kernel+0xad/0x110 +# drm_ioctl+0x235/0x4b0 +# __x64_sys_ioctl+0x8f/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f6b0d637c5b +# 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 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 +# RSP: 002b:00007ffc42b13670 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f6b0d637c5b +# RDX: 00007ffc42b13710 RSI: 00000000c05064a7 RDI: 0000000000000003 +# RBP: 00007ffc42b13710 R08: 0000000000000007 R09: 000055eea2741720 +# R10: 9fb9be4e118bfa43 R11: 0000000000000246 R12: 00000000c05064a7 +# R13: 0000000000000003 R14: 00000000c05064a7 R15: 00007ffc42b13710 +# +# irq event stamp: 0 +# hardirqs last enabled at (0): [<0000000000000000>] 0x0 +# hardirqs last disabled at (0): [] copy_process+0xaf3/0x2eb0 +# softirqs last enabled at (0): [] copy_process+0xaf3/0x2eb0 +# softirqs last disabled at (0): [<0000000000000000>] 0x0 +# ---[ end trace 0000000000000000 ]--- +# i915 0000:00:02.0: [drm] *ERROR* PPS state mismatch +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* Failed to read DPCD register 0x92 +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# i915 0000:00:02.0: [drm] *ERROR* AUX A/DDI A/PHY A: not done (status 0x00000000) +# [IGT] kms_lease: starting subtest page-flip-implicit-plane +# [IGT] kms_lease: starting dynamic subtest pipe-A-eDP-1 +# i915 0000:00:02.0: [drm] *ERROR* [CRTC:70:pipe A] flip_done timed out +# i915 0000:00:02.0: [drm] *ERROR* flip_done timed out +# i915 0000:00:02.0: [drm] *ERROR* [CRTC:70:pipe A] commit wait timed out +# INFO: task kms_lease:1271 blocked for more than 122 seconds. +# Tainted: G W 6.13.0-rc2-gfb6fd142a8eb #1 +# "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +# task:kms_lease state:D stack:12720 pid:1271 tgid:1271 ppid:184 flags:0x00004006 +# Call Trace: +# +# __schedule+0x495/0xd20 +# schedule+0x35/0x120 +# drm_vblank_work_flush+0x91/0xf0 +# intel_wait_for_vblank_workers+0x58/0x90 +# intel_atomic_commit_tail+0xa86/0x15f0 +# intel_atomic_commit+0x257/0x2a0 +# drm_atomic_commit+0xac/0xe0 +# set_property_atomic+0x91/0x160 +# drm_mode_obj_set_property_ioctl+0xc1/0x110 +# drm_ioctl_kernel+0xad/0x110 +# drm_ioctl+0x235/0x4b0 +# __x64_sys_ioctl+0x8f/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f6b0d637c5b +# RSP: 002b:00007ffc42b13650 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 00007ffc42b14270 RCX: 00007f6b0d637c5b +# RDX: 00007ffc42b136e0 RSI: 00000000c01864ba RDI: 0000000000000003 +# RBP: 00007ffc42b136e0 R08: 0000000000000000 R09: 000055eea2741750 +# R10: 00007f6b0d71d310 R11: 0000000000000246 R12: 00000000c01864ba +# R13: 0000000000000003 R14: 0000000000000000 R15: 000055eea27378d0 +# +# INFO: lockdep is turned off. + +# The test alternates between failing and timing out on reruns, causing the pipeline to fail +gen9_exec_parse@unaligned-access diff --git a/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt index ed9f7b576843..0e08fff741aa 100644 --- a/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-jsl-fails.txt @@ -1,15 +1,16 @@ -core_setmaster@master-drop-set-user,Fail +drm_fdinfo@busy-check-all,Fail i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail i915_module_load@resize-bar,Fail -i915_pm_rpm@gem-execbuf-stress,Timeout -i915_pm_rpm@module-reload,Fail -kms_flip@plain-flip-fb-recreate,Fail +kms_flip@dpms-off-confusion,Fail +kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset,Fail +kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail +kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail @@ -17,6 +18,7 @@ kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail +kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail @@ -26,19 +28,15 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail +kms_frontbuffer_tracking@fbc-rgb565-draw-blt,Timeout kms_lease@lease-uevent,Fail -kms_pm_rpm@legacy-planes,Timeout -kms_pm_rpm@legacy-planes-dpms,Timeout kms_pm_rpm@modeset-stress-extra-wait,Timeout -kms_pm_rpm@universal-planes,Timeout -kms_pm_rpm@universal-planes-dpms,Timeout +kms_rotation_crc@bad-pixel-format,Fail kms_rotation_crc@multiplane-rotation,Fail kms_rotation_crc@multiplane-rotation-cropping-bottom,Fail kms_rotation_crc@multiplane-rotation-cropping-top,Fail perf@i915-ref-count,Fail -perf_pmu@busy-accuracy-50,Fail perf_pmu@module-unload,Fail -perf_pmu@most-busy-idle-check-all,Fail perf_pmu@rc6,Crash sysfs_heartbeat_interval@long,Timeout sysfs_heartbeat_interval@off,Timeout diff --git a/drivers/gpu/drm/ci/xfails/i915-jsl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-jsl-flakes.txt index 5c3ef4486b9d..8b2aefd1cc52 100644 --- a/drivers/gpu/drm/ci/xfails/i915-jsl-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-jsl-flakes.txt @@ -1,13 +1,6 @@ # Board Name: acer-cb317-1h-c3z6-dedede -# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12475 +# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13349 # Failure Rate: 100 -# IGT Version: 1.28-ga73311079 -# Linux Version: 6.12.0-rc1 -kms_flip@flip-vs-panning-interruptible - -# Board Name: acer-cb317-1h-c3z6-dedede -# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12476 -# Failure Rate: 100 -# IGT Version: 1.28-ga73311079 -# Linux Version: 6.12.0-rc1 -kms_universal_plane@cursor-fb-leak +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_flip@flip-vs-fences-interruptible diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt index 6ec2f83ffe13..dc722d6a774e 100644 --- a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt @@ -37,3 +37,115 @@ tools_test.* # GPU hang sysfs_timeslice_.* sysfs_heartbeat_.* + +device_reset@unbind-reset-rebind +# [IGT] device_reset: starting subtest unbind-reset-rebind +# i915 0000:00:02.0: [drm] Found kabylake (device ID 5917) display version 9.00 stepping C0 +# i915 0000:00:02.0: vgaarb: deactivate vga console +# i915 0000:00:02.0: [drm] *ERROR* DPLL0 not locked +# ------------[ cut here ]------------ +# i915 0000:00:02.0: [drm] drm_WARN_ON((val & (1 << 30)) == 0) +# WARNING: CPU: 4 PID: 472 at drivers/gpu/drm/i915/display/intel_cdclk.c:944 skl_get_cdclk+0x1ca/0x360 +# Modules linked in: +# CPU: 4 UID: 0 PID: 472 Comm: device_reset Not tainted 6.13.0-rc2-ge95c88d68ac3 #1 +# Hardware name: HP Nami/Nami, BIOS 09/19/2019 +# RIP: 0010:skl_get_cdclk+0x1ca/0x360 +# Code: 67 50 4d 85 e4 0f 84 89 01 00 00 e8 e0 16 13 00 48 c7 c1 a0 71 5f 9a 4c 89 e2 48 c7 c7 67 56 69 9a 48 89 c6 e8 67 a1 72 ff 90 <0f> 0b 90 90 8b 43 08 8b 53 04 89 43 0c 89 03 85 d2 0f 85 26 ff ff +# RSP: 0018:ffffacba40f5fbd0 EFLAGS: 00010282 +# RAX: 0000000000000000 RBX: ffff953182571058 RCX: 00000000ffffdfff +# RDX: 0000000000000000 RSI: ffffacba40f5fa80 RDI: 0000000000000001 +# RBP: ffff953182570d68 R08: 0000000000009ffb R09: 00000000ffffdfff +# R10: 00000000ffffdfff R11: ffffffff9a88c8a0 R12: ffff953180d3f4a0 +# R13: 0000000000000000 R14: ffff953182570d68 R15: 0000000000000000 +# FS: 00007f74989c46c0(0000) GS:ffff9534eed00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 00007f1df530eff8 CR3: 0000000102302002 CR4: 00000000003706f0 +# DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +# DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +# Call Trace: +# +# intel_update_cdclk+0x1c/0x90 +# intel_cdclk_init_hw+0x46e/0x4c0 +# intel_power_domains_init_hw+0x3eb/0x770 +# intel_display_driver_probe_noirq+0x85/0x230 +# i915_driver_probe+0x66d/0xc60 +# local_pci_probe+0x3a/0x90 +# pci_device_probe+0xb5/0x180 +# really_probe+0xc9/0x2b0 +# __driver_probe_device+0x6e/0x110 +# device_driver_attach+0x42/0xa0 +# bind_store+0x71/0xc0 +# kernfs_fop_write_iter+0x121/0x1c0 +# vfs_write+0x2a8/0x530 +# ksys_write+0x6f/0xf0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f7499e662c0 +# Code: 40 00 48 8b 15 41 9b 0d 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 80 3d 21 23 0e 00 00 74 17 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 58 c3 0f 1f 80 00 00 00 00 48 83 ec 28 48 89 +# RSP: 002b:00007ffffaf36a68 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 +# RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f7499e662c0 +# RDX: 000000000000000c RSI: 00007ffffaf36b50 RDI: 0000000000000003 +# RBP: 000000000000000c R08: 0000000000000007 R09: 000055b37d0964a0 +# R10: 0000000000000000 R11: 0000000000000202 R12: 00007ffffaf36b50 +# R13: 0000000000000003 R14: 000055b3526a7220 R15: 00007f749a0dc020 +# +# irq event stamp: 28591 +# hardirqs last enabled at (28625): [] __up_console_sem+0x4d/0x60 +# hardirqs last disabled at (28658): [] __up_console_sem+0x32/0x60 +# softirqs last enabled at (28688): [] handle_softirqs+0x310/0x3f0 +# softirqs last disabled at (28701): [] __irq_exit_rcu+0xa1/0xc0 +# ---[ end trace 0000000000000000 ]--- +# ------------[ cut here ]------------ +# i915 0000:00:02.0: [drm] drm_WARN_ON((val & (1 << 30)) == 0) +# WARNING: CPU: 1 PID: 472 at drivers/gpu/drm/i915/display/intel_cdclk.c:944 skl_get_cdclk+0x1ca/0x360 +# Modules linked in: +# CPU: 1 UID: 0 PID: 472 Comm: device_reset Tainted: G W 6.13.0-rc2-ge95c88d68ac3 #1 +# Tainted: [W]=WARN +# Hardware name: HP Nami/Nami, BIOS 09/19/2019 +# RIP: 0010:skl_get_cdclk+0x1ca/0x360 +# Code: 67 50 4d 85 e4 0f 84 89 01 00 00 e8 e0 16 13 00 48 c7 c1 a0 71 5f 9a 4c 89 e2 48 c7 c7 67 56 69 9a 48 89 c6 e8 67 a1 72 ff 90 <0f> 0b 90 90 8b 43 08 8b 53 04 89 43 0c 89 03 85 d2 0f 85 26 ff ff +# RSP: 0018:ffffacba40f5fb98 EFLAGS: 00010286 +# RAX: 0000000000000000 RBX: ffffacba40f5fbbc RCX: 00000000ffffdfff +# RDX: 0000000000000000 RSI: ffffacba40f5fa48 RDI: 0000000000000001 +# RBP: ffff953182570d68 R08: 0000000000009ffb R09: 00000000ffffdfff +# R10: 00000000ffffdfff R11: ffffffff9a88c8a0 R12: ffff953180d3f4a0 +# R13: ffff953182573208 R14: ffff953182570d68 R15: 0000000000000000 +# FS: 00007f74989c46c0(0000) GS:ffff9534eec40000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 00007f2b6598ee00 CR3: 0000000102302001 CR4: 00000000003706f0 +# DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +# DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +# Call Trace: +# +# gen9_disable_dc_states+0x86/0x300 +# intel_power_well_enable+0x56/0x70 +# __intel_display_power_get_domain.part.0+0x4d/0x70 +# intel_power_domains_init_hw+0x95/0x770 +# intel_display_driver_probe_noirq+0x85/0x230 +# i915_driver_probe+0x66d/0xc60 +# local_pci_probe+0x3a/0x90 +# pci_device_probe+0xb5/0x180 +# really_probe+0xc9/0x2b0 +# __driver_probe_device+0x6e/0x110 +# device_driver_attach+0x42/0xa0 +# bind_store+0x71/0xc0 +# kernfs_fop_write_iter+0x121/0x1c0 +# vfs_write+0x2a8/0x530 +# ksys_write+0x6f/0xf0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f7499e662c0 +# Code: 40 00 48 8b 15 41 9b 0d 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 80 3d 21 23 0e 00 00 74 17 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 58 c3 0f 1f 80 00 00 00 00 48 83 ec 28 48 89 +# RSP: 002b:00007ffffaf36a68 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 +# RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f7499e662c0 +# RDX: 000000000000000c RSI: 00007ffffaf36b50 RDI: 0000000000000003 +# RBP: 000000000000000c R08: 0000000000000007 R09: 000055b37d0964a0 +# R10: 0000000000000000 R11: 0000000000000202 R12: 00007ffffaf36b50 +# R13: 0000000000000003 R14: 000055b3526a7220 R15: 00007f749a0dc020 +# +# irq event stamp: 29605 +# hardirqs last enabled at (29617): [] __up_console_sem+0x4d/0x60 +# hardirqs last disabled at (29634): [] __up_console_sem+0x32/0x60 +# softirqs last enabled at (29630): [] handle_softirqs+0x310/0x3f0 +# softirqs last disabled at (29625): [] __irq_exit_rcu+0xa1/0xc0 +# ---[ end trace 0000000000000000 ]--- diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt index 461ef69ef08a..93d42b146df9 100644 --- a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt @@ -1,64 +1,24 @@ -api_intel_allocator@fork-simple-stress-signal,Timeout -api_intel_allocator@open-vm,Timeout -api_intel_allocator@simple-allocator,Timeout -api_intel_bb@lot-of-buffers,Timeout -api_intel_bb@object-reloc-keep-cache,Timeout -api_intel_bb@offset-control,Timeout -api_intel_bb@render-ccs,Timeout -api_intel_bb@reset-bb,Timeout -core_auth@basic-auth,Timeout -core_hotunplug@hotrebind,Timeout -core_setmaster@master-drop-set-user,Fail -debugfs_test@read_all_entries_display_on,Timeout -drm_read@empty-block,Timeout -dumb_buffer@create-clear,Timeout -dumb_buffer@invalid-bpp,Timeout -gen3_render_tiledx_blits,Timeout -gen7_exec_parse@basic-allocation,Timeout -gen9_exec_parse@batch-invalid-length,Timeout -gen9_exec_parse@bb-secure,Timeout -gen9_exec_parse@secure-batches,Timeout -gen9_exec_parse@shadow-peek,Timeout -gen9_exec_parse@unaligned-jump,Timeout -i915_getparams_basic@basic-subslice-total,Timeout -i915_hangman@gt-engine-hang,Timeout +api_intel_allocator@reopen,Timeout +api_intel_bb@destroy-bb,Timeout +core_hotunplug@hotrebind-lateclose,Timeout +drm_read@short-buffer-block,Timeout +dumb_buffer@map-valid,Timeout i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail i915_module_load@resize-bar,Fail -i915_pciid,Timeout -i915_pipe_stress@stress-xrgb8888-ytiled,Timeout -i915_pm_rpm@gem-execbuf-stress,Timeout i915_pm_rps@engine-order,Timeout -i915_pm_rps@thresholds-idle-park,Timeout -i915_query@engine-info,Timeout -i915_query@query-topology-kernel-writes,Timeout -i915_query@test-query-geometry-subslices,Timeout kms_lease@lease-uevent,Fail kms_rotation_crc@multiplane-rotation,Fail perf@i915-ref-count,Fail perf_pmu@busy,Timeout perf_pmu@enable-race,Timeout -perf_pmu@event-wait,Timeout -perf_pmu@faulting-read,Timeout -perf_pmu@gt-awake,Timeout -perf_pmu@interrupts,Timeout perf_pmu@module-unload,Fail -perf_pmu@most-busy-idle-check-all,Timeout perf_pmu@rc6,Crash -perf_pmu@render-node-busy-idle,Fail perf_pmu@semaphore-wait-idle,Timeout -prime_busy@after,Timeout -prime_mmap@test_aperture_limit,Timeout -prime_mmap@test_map_unmap,Timeout prime_mmap@test_refcounting,Timeout -prime_self_import@basic-with_one_bo,Timeout -sriov_basic@enable-vfs-autoprobe-off,Timeout -syncobj_basic@bad-destroy,Timeout -syncobj_basic@bad-flags-fd-to-handle,Timeout -syncobj_basic@create-signaled,Timeout -syncobj_eventfd@invalid-bad-pad,Timeout -syncobj_eventfd@timeline-wait-before-signal,Timeout +sriov_basic@enable-vfs-bind-unbind-each-numvfs-all,Timeout +syncobj_basic@illegal-fd-to-handle,Timeout syncobj_wait@invalid-multi-wait-unsubmitted-signaled,Timeout syncobj_wait@invalid-signal-illegal-handle,Timeout syncobj_wait@invalid-single-wait-all-unsubmitted,Timeout @@ -66,7 +26,6 @@ syncobj_wait@multi-wait-all-submitted,Timeout syncobj_wait@multi-wait-for-submit-submitted-signaled,Timeout syncobj_wait@wait-any-complex,Timeout syncobj_wait@wait-delayed-signal,Timeout -template@A,Timeout xe_module_load@force-load,Fail xe_module_load@load,Fail xe_module_load@many-reload,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt index b47df5855e8d..938377896841 100644 --- a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt @@ -35,3 +35,16 @@ syncobj_wait.* # Kernel panic and test hangs with multiple kms tests kms_.* + +# The test alternates between failing and timing out on reruns, causing the pipeline to fail +api_intel_allocator@reopen +api_intel_bb@destroy-bb +core_hotunplug@hotrebind-lateclose +dumb_buffer@map-valid +i915_pm_rps@engine-order +perf_pmu@busy +perf_pmu@enable-race +perf_pmu@semaphore-wait-idle +prime_mmap@test_refcounting +sriov_basic@enable-vfs-bind-unbind-each-numvfs-all +syncobj_basic@illegal-fd-to-handle diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt index 0ce240e3aa07..1cb6978c86dc 100644 --- a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt @@ -1,5 +1,4 @@ core_setmaster@master-drop-set-shared-fd,Fail -core_setmaster@master-drop-set-user,Fail i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail @@ -7,12 +6,10 @@ i915_module_load@resize-bar,Fail i915_pm_rpm@gem-execbuf-stress,Timeout i915_pm_rpm@module-reload,Fail i915_pm_rpm@system-suspend-execbuf,Timeout -i915_pm_rps@engine-order,Fail -kms_big_fb@linear-16bpp-rotate-180,Timeout -kms_cursor_legacy@short-flip-before-cursor-atomic-transitions,Timeout +kms_async_flips@test-time-stamp,Timeout +kms_ccs@crc-sprite-planes-basic-y-tiled-ccs,Timeout kms_dirtyfb@default-dirtyfb-ioctl,Fail kms_dirtyfb@fbc-dirtyfb-ioctl,Fail -kms_fb_coherency@memset-crc,Crash kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -34,18 +31,12 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail kms_frontbuffer_tracking@fbc-tiling-linear,Fail -kms_frontbuffer_tracking@fbc-1p-indfb-fliptrack-mmap-gtt,Timeout kms_lease@lease-uevent,Fail +kms_lease@page-flip-implicit-plane,Timeout kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout -kms_pm_rpm@modeset-stress-extra-wait,Timeout -kms_pm_rpm@universal-planes,Timeout -kms_pm_rpm@universal-planes-dpms,Timeout -kms_rotation_crc@primary-rotation-180,Timeout -kms_vblank@query-forked-hang,Timeout perf@i915-ref-count,Fail perf_pmu@module-unload,Fail perf_pmu@rc6,Crash diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt index 60b8d1c64e70..19a289617080 100644 --- a/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt @@ -4,3 +4,10 @@ # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 kms_pm_rpm@modeset-lpsp-stress + +# Board Name: dell-latitude-5400-8665U-sarien +# Bug Report: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13351 +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +gen9_exec_parse@unaligned-access diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt index 8e0efc80d510..4f176c04ec4e 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt @@ -1,8 +1,5 @@ -fbdev@eof,Fail -fbdev@read,Fail kms_3d,Fail kms_bw@connected-linear-tiling-1-displays-1920x1080p,Fail -kms_bw@connected-linear-tiling-1-displays-2160x1440p,Fail kms_bw@connected-linear-tiling-1-displays-2560x1440p,Fail kms_bw@connected-linear-tiling-1-displays-3840x2160p,Fail kms_bw@connected-linear-tiling-2-displays-1920x1080p,Fail @@ -22,6 +19,6 @@ kms_cursor_legacy@cursor-vs-flip-atomic,Fail kms_cursor_legacy@cursor-vs-flip-legacy,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail -kms_lease@lease-uevent,Fail -kms_rmfb@close-fd,Fail +kms_flip@flip-vs-suspend,Fail kms_flip@flip-vs-suspend-interruptible,Fail +kms_lease@lease-uevent,Fail diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt index 2e5bf6ae25f2..2956567c3048 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt @@ -39,3 +39,10 @@ kms_cursor_legacy@cursor-vs-flip-atomic-transitions # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 kms_prop_blob@invalid-set-prop + +# Board Name: mt8173-elm-hana +# Bug Report: https://lore.kernel.org/dri-devel/c0b4cded-0971-4abb-9965-2acf4602d7cd@collabora.com/T/#u +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_bw@connected-linear-tiling-1-displays-2160x1440p diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt index 8198e06344a3..d0db51874aef 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt @@ -15,3 +15,8 @@ tools_test.* # Currently fails and causes coverage loss for other tests # since core_getversion also fails. core_hotunplug.* + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt index 845f852bb4a0..5a063361d7f2 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt @@ -1,16 +1,12 @@ -core_setmaster@master-drop-set-shared-fd,Fail +core_setmaster@master-drop-set-user,Fail dumb_buffer@create-clear,Crash -fbdev@eof,Fail -fbdev@pan,Fail -fbdev@read,Fail -fbdev@unaligned-read,Fail kms_bw@connected-linear-tiling-1-displays-1920x1080p,Fail -kms_bw@connected-linear-tiling-1-displays-2160x1440p,Fail kms_bw@connected-linear-tiling-1-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-1-displays-3840x2160p,Fail kms_bw@linear-tiling-1-displays-1920x1080p,Fail +kms_bw@linear-tiling-1-displays-2160x1440p,Fail kms_bw@linear-tiling-1-displays-3840x2160p,Fail -kms_color@invalid-gamma-lut-sizes,Fail +kms_cursor_legacy@cursor-vs-flip-atomic,Fail kms_flip@flip-vs-panning-vs-hang,Fail kms_flip@flip-vs-suspend,Fail kms_lease@lease-uevent,Fail -kms_rmfb@close-fd,Fail diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt index 8198e06344a3..d0db51874aef 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt @@ -15,3 +15,8 @@ tools_test.* # Currently fails and causes coverage loss for other tests # since core_getversion also fails. core_hotunplug.* + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt index 066d24ee3e08..7752adff05c1 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt @@ -1,4 +1,7 @@ kms_3d,Fail +kms_cursor_legacy@forked-bo,Fail +kms_cursor_legacy@forked-move,Fail +kms_cursor_legacy@single-bo,Fail kms_cursor_legacy@torture-bo,Fail kms_force_connector_basic@force-edid,Fail kms_hdmi_inject@inject-4k,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt index 6dbc2080347d..e4a8f8352cd6 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt @@ -15,4 +15,3 @@ kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail kms_plane_alpha_blend@alpha-7efc,Fail kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail -kms_rmfb@close-fd,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt index d74e04405e65..8910afb6acf2 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt @@ -18,3 +18,17 @@ msm/msm_shrink@copy-gpu-oom-32 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 msm/msm_shrink@copy-gpu-oom-8 + +# Board Name: sc7180-trogdor-kingoftown +# Bug Report: https://gitlab.freedesktop.org/drm/msm/-/issues/68 +# Failure Rate: 40 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_lease@page-flip-implicit-plane + +# Board Name: sc7180-trogdor-kingoftown +# Bug Report: https://gitlab.freedesktop.org/drm/msm/-/issues/69 +# Failure Rate: 20 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_plane@plane-position-hole-dpms diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt index c2833eee1c4b..478d7c161616 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt @@ -23,3 +23,8 @@ kms_flip@2x-wf_vblank-ts-check # Hangs the machine kms_cursor_crc@cursor-random-max-size + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt index 6dbc2080347d..e4a8f8352cd6 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt @@ -15,4 +15,3 @@ kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail kms_plane_alpha_blend@alpha-7efc,Fail kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail -kms_rmfb@close-fd,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt index 7c69c1f1d55b..ef9318afcd89 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt @@ -17,3 +17,8 @@ tools_test.* # Currently fails and causes coverage loss for other tests # since core_getversion also fails. core_hotunplug.* + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt index fa8c7e663858..7a2ab58b706f 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt @@ -1,4 +1,3 @@ -drm_read@invalid-buffer,Fail kms_color@ctm-0-25,Fail kms_color@ctm-0-50,Fail kms_color@ctm-0-75,Fail @@ -28,4 +27,3 @@ kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail kms_plane_cursor@overlay,Fail kms_plane_cursor@viewport,Fail -kms_rmfb@close-fd,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt index 94783cafc21a..2ce7f7e23a01 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt @@ -30,3 +30,8 @@ kms_cursor_crc.* # IGT Version: 1.28-ga73311079 # Linux Version: 6.11.0-rc2 kms_content_protection@uevent + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt index 4892c0c70a6d..8d26b23133aa 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sm8350-hdk-fails.txt @@ -7,9 +7,4 @@ kms_cursor_legacy@torture-bo,Fail kms_cursor_legacy@torture-move,Fail kms_hdmi_inject@inject-4k,Fail kms_lease@lease-uevent,Fail -kms_plane_alpha_blend@alpha-7efc,Fail -kms_plane_alpha_blend@alpha-basic,Fail -kms_plane_alpha_blend@alpha-opaque-fb,Fail -kms_plane_alpha_blend@alpha-transparent-fb,Fail -kms_plane_alpha_blend@constant-alpha-max,Fail msm/msm_recovery@gpu-fault-parallel,Fail diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt index 90282dfa19f4..ba9160d4d8eb 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt @@ -1,24 +1,10 @@ +core_setmaster@master-drop-set-root,Crash +core_setmaster@master-drop-set-shared-fd,Crash core_setmaster@master-drop-set-user,Crash +core_setmaster_vs_auth,Crash dumb_buffer@create-clear,Crash fbdev@pan,Crash -kms_bw@linear-tiling-2-displays-1920x1080p,Fail -kms_cursor_crc@cursor-onscreen-32x10,Crash -kms_cursor_crc@cursor-onscreen-32x32,Crash -kms_cursor_crc@cursor-onscreen-64x64,Crash -kms_cursor_crc@cursor-random-32x10,Crash -kms_cursor_crc@cursor-sliding-32x10,Crash -kms_cursor_crc@cursor-sliding-32x32,Crash -kms_cursor_crc@cursor-sliding-64x21,Crash -kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail -kms_cursor_legacy@cursor-vs-flip-legacy,Fail -kms_cursor_legacy@flip-vs-cursor-crc-atomic,Crash -kms_flip@flip-vs-panning-vs-hang,Crash -kms_invalid_mode@int-max-clock,Crash -kms_lease@invalid-create-leases,Fail -kms_pipe_crc_basic@read-crc-frame-sequence,Crash -kms_plane@pixel-format,Crash -kms_plane@pixel-format-source-clamping,Crash +kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail +kms_flip@flip-vs-modeset-vs-hang,Crash kms_prop_blob@invalid-set-prop,Crash -kms_properties@get_properties-sanity-atomic,Crash -kms_properties@get_properties-sanity-non-atomic,Crash -kms_rmfb@close-fd,Crash +kms_prop_blob@invalid-set-prop-any,Crash diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt index 83a38853b4af..2803d0d80192 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt @@ -2,6 +2,7 @@ dumb_buffer@create-clear,Crash kms_atomic_transition@modeset-transition,Fail kms_atomic_transition@modeset-transition-fencing,Fail kms_atomic_transition@plane-toggle-modeset-transition,Fail +kms_bw@connected-linear-tiling-1-displays-2160x1440p,Fail kms_color@gamma,Fail kms_color@legacy-gamma,Fail kms_cursor_crc@cursor-alpha-opaque,Fail @@ -24,6 +25,7 @@ kms_cursor_crc@cursor-rapid-movement-32x32,Fail kms_cursor_crc@cursor-rapid-movement-64x21,Fail kms_cursor_crc@cursor-rapid-movement-64x64,Fail kms_cursor_crc@cursor-size-change,Fail +kms_cursor_crc@cursor-size-hints,Fail kms_cursor_crc@cursor-sliding-32x10,Fail kms_cursor_crc@cursor-sliding-32x32,Fail kms_cursor_crc@cursor-sliding-64x21,Fail @@ -32,6 +34,7 @@ kms_cursor_edge_walk@64x64-left-edge,Fail kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail kms_cursor_legacy@cursor-vs-flip-atomic,Fail +kms_cursor_legacy@cursor-vs-flip-atomic-transitions,Fail kms_cursor_legacy@cursor-vs-flip-legacy,Fail kms_cursor_legacy@cursor-vs-flip-toggle,Fail kms_cursor_legacy@flip-vs-cursor-atomic,Fail @@ -41,14 +44,11 @@ kms_cursor_legacy@flip-vs-cursor-legacy,Fail kms_cursor_legacy@long-nonblocking-modeset-vs-cursor-atomic,Fail kms_flip@basic-flip-vs-wf_vblank,Fail kms_flip@blocking-wf_vblank,Fail -kms_flip@flip-vs-absolute-wf_vblank,Fail -kms_flip@flip-vs-blocking-wf-vblank,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning,Fail kms_flip@flip-vs-panning-interruptible,Fail kms_flip@flip-vs-panning-vs-hang,Fail kms_flip@modeset-vs-vblank-race,Fail -kms_flip@modeset-vs-vblank-race-interruptible,Fail kms_flip@plain-flip-fb-recreate,Fail kms_flip@plain-flip-fb-recreate-interruptible,Fail kms_flip@plain-flip-ts-check,Fail @@ -64,14 +64,11 @@ kms_pipe_crc_basic@nonblocking-crc,Fail kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail kms_pipe_crc_basic@read-crc,Fail kms_pipe_crc_basic@read-crc-frame-sequence,Fail -kms_plane@pixel-format,Crash -kms_plane@pixel-format-source-clamping,Crash +kms_plane@pixel-format,Fail +kms_plane@pixel-format-source-clamping,Fail kms_plane@plane-panning-bottom-right,Fail kms_plane@plane-panning-top-left,Fail kms_plane@plane-position-covered,Fail kms_plane@plane-position-hole,Fail -kms_plane@plane-position-hole-dpms,Fail kms_plane_cursor@primary,Fail -kms_plane_multiple@tiling-none,Fail -kms_rmfb@close-fd,Fail kms_universal_plane@universal-plane-functional,Fail diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt index 56f7d4f1ed15..348b4ce7eb4b 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt @@ -74,3 +74,59 @@ kms_bw@linear-tiling-2-displays-2160x1440p # IGT Version: 1.28-ga73311079 # Linux Version: 6.11.0-rc5 kms_flip@flip-vs-expired-vblank + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/f944dd08-c88c-49ae-aff0-274374550a93@collabora.com/T/#u +# Failure Rate: 40 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_bw@linear-tiling-1-displays-2160x1440p + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/afa2d3bf-29f2-488d-8cc9-f30d461444b0@collabora.com/T/#u +# Failure Rate: 80 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_plane_multiple@tiling-none + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/6fdaa97f-c1a5-4216-831f-dbb7c5f90498@collabora.com/T/#u +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_bw@linear-tiling-1-displays-1920x1080p + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/616aa015-9574-4527-9d07-d8d698bbcc3c@collabora.com/T/#u +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_plane@plane-position-hole-dpms + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/7a1b888f-d7db-4ed7-96cd-3975ace837fb@collabora.com/T/#u +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_flip@flip-vs-absolute-wf_vblank + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/f17fffb6-abc4-464e-8465-395311b01f6a@collabora.com/T/#u +# Failure Rate: 100 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_flip@flip-vs-blocking-wf-vblank + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/9b590b26-1bf9-4951-b6a3-ef6c67e6a1c6@collabora.com/T/#u +# Failure Rate: 60 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_bw@linear-tiling-2-displays-1920x1080p + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/dri-devel/059545fa-65b1-4f5c-a13e-4d2898679f51@collabora.com/T/#u +# Failure Rate: 20 +# IGT Version: 1.29-g33adea9eb +# Linux Version: 6.13.0-rc2 +kms_flip@modeset-vs-vblank-race-interruptible diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt index eb16b29dee48..e8e994d92557 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt @@ -18,3 +18,8 @@ tools_test.* # Currently fails and causes coverage loss for other tests # since core_getversion also fails. core_hotunplug.* + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt index 9c9e048725f8..adbcdd0f28d2 100644 --- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt +++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt @@ -23,3 +23,8 @@ tools_test.* # Currently fails and causes coverage loss for other tests # since core_getversion also fails. core_hotunplug.* + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt index 71c02104a683..85647eca4e55 100644 --- a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt +++ b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt @@ -1,12 +1,5 @@ -kms_cursor_crc@cursor-rapid-movement-128x128,Fail -kms_cursor_crc@cursor-rapid-movement-128x42,Fail -kms_cursor_crc@cursor-rapid-movement-256x256,Fail kms_cursor_crc@cursor-rapid-movement-256x85,Fail kms_cursor_crc@cursor-rapid-movement-32x10,Fail -kms_cursor_crc@cursor-rapid-movement-32x32,Fail -kms_cursor_crc@cursor-rapid-movement-512x170,Fail -kms_cursor_crc@cursor-rapid-movement-512x512,Fail -kms_cursor_crc@cursor-rapid-movement-64x21,Fail kms_cursor_crc@cursor-rapid-movement-64x64,Fail kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail @@ -21,7 +14,6 @@ kms_cursor_legacy@flip-vs-cursor-legacy,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail kms_lease@lease-uevent,Fail -kms_pipe_crc_basic@nonblocking-crc,Fail kms_writeback@writeback-check-output,Fail kms_writeback@writeback-check-output-XRGB2101010,Fail kms_writeback@writeback-fb-id,Fail diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt index b3d16e82e9a2..319789806271 100644 --- a/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt +++ b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt @@ -1,8 +1,9 @@ # keeps printing vkms_vblank_simulate: vblank timer overrun and never ends kms_invalid_mode@int-max-clock -# Kernel panic -kms_cursor_crc@cursor-rapid-movement-32x10 +# kernel panic seen with kms_cursor_crc tests +kms_cursor_crc.* +# kms_cursor_crc@cursor-rapid-movement-32x10 # Oops: 0000 [#1] PREEMPT SMP NOPTI # CPU: 0 PID: 2635 Comm: kworker/u8:13 Not tainted 6.9.0-rc7-g40935263a1fd #1 # Hardware name: ChromiumOS crosvm, BIOS 0 @@ -52,7 +53,7 @@ kms_cursor_crc@cursor-rapid-movement-32x10 # FS: 0000000000000000(0000) GS:ffffa2ad2bc00000(0000) knlGS:0000000000000000 # CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -kms_cursor_crc@cursor-rapid-movement-256x85 +#kms_cursor_crc@cursor-rapid-movement-256x85 # [drm:drm_crtc_add_crc_entry] *ERROR* Overflow of CRC buffer, userspace reads too slow. # Oops: 0000 [#1] PREEMPT SMP NOPTI # CPU: 1 PID: 10 Comm: kworker/u8:0 Not tainted 6.9.0-rc7-g646381cde463 #1 @@ -104,7 +105,7 @@ kms_cursor_crc@cursor-rapid-movement-256x85 # CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 # CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0 -kms_cursor_crc@cursor-onscreen-256x256 +#kms_cursor_crc@cursor-onscreen-256x256 # Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI # CPU: 1 PID: 1913 Comm: kworker/u8:6 Not tainted 6.10.0-rc5-g8a28e73ebead #1 # Hardware name: ChromiumOS crosvm, BIOS 0 @@ -258,6 +259,535 @@ kms_cursor_edge_walk@128x128-left-edge # CR2: 0000000000000018 CR3: 0000000101710000 CR4: 0000000000350ef0 # vkms_vblank_simulate: vblank timer overrun +# DEBUG - Begin test kms_cursor_crc@cursor-rapid-movement-64x64 +# ------------[ cut here ]------------ +# WARNING: CPU: 1 PID: 1250 at drivers/gpu/drm/vkms/vkms_crtc.c:139 vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Modules linked in: vkms +# CPU: 1 UID: 0 PID: 1250 Comm: kms_cursor_crc Not tainted 6.13.0-rc2-ge95c88d68ac3 #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# RIP: 0010:vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Code: f7 48 89 f3 e8 d0 bf ee ec 48 8b 83 50 01 00 00 a8 01 75 15 48 8b bb a0 01 00 00 e8 59 05 95 ec 48 89 df 5b e9 50 05 95 ec 90 <0f> 0b 90 eb e5 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 +# RSP: 0018:ffff9fb640aafb08 EFLAGS: 00010202 +# RAX: ffff8e7240859e05 RBX: ffff8e7241cd6400 RCX: ffffffffae496b65 +# RDX: ffffffffad2d1f80 RSI: 0000000000000000 RDI: 0000000000000000 +# RBP: 0000000000000000 R08: 0000000000000034 R09: 0000000000000002 +# R10: 0000000047dd15a5 R11: 00000000547dd15a R12: ffff8e72590cc000 +# R13: 0000000000000000 R14: 00000000ffffffff R15: 0000000000000000 +# FS: 00007f0942ad56c0(0000) GS:ffff8e726bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 00007f0942ad0008 CR3: 0000000118d1e000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __warn+0x8c/0x190 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? report_bug+0x164/0x190 +# ? handle_bug+0x54/0x90 +# ? exc_invalid_op+0x17/0x70 +# ? asm_exc_invalid_op+0x1a/0x20 +# ? __pfx_drm_property_free_blob+0x10/0x10 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? vkms_atomic_crtc_destroy_state+0x10/0x40 [vkms] +# drm_atomic_state_default_clear+0x137/0x2f0 +# __drm_atomic_state_free+0x6c/0xb0 +# drm_atomic_helper_update_plane+0x100/0x150 +# drm_mode_cursor_universal+0x10e/0x270 +# drm_mode_cursor_common+0x115/0x240 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# drm_mode_cursor_ioctl+0x4a/0x70 +# drm_ioctl_kernel+0xb0/0x110 +# drm_ioctl+0x235/0x4b0 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# __x64_sys_ioctl+0x92/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f0943a84cdb +# 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 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 +# RSP: 002b:00007fff267d68d0 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 000000000000005a RCX: 00007f0943a84cdb +# RDX: 00007fff267d6960 RSI: 00000000c01c64a3 RDI: 0000000000000005 +# RBP: 00007fff267d6960 R08: 0000000000000007 R09: 00005619a60f3450 +# R10: fe95a83851609dee R11: 0000000000000246 R12: 00000000c01c64a3 +# R13: 0000000000000005 R14: 00005619a3cd2c68 R15: 00005619a608c830 +# +# irq event stamp: 57793 +# hardirqs last enabled at (57799): [] __up_console_sem+0x4d/0x60 +# hardirqs last disabled at (57804): [] __up_console_sem+0x32/0x60 +# softirqs last enabled at (45586): [] handle_softirqs+0x310/0x3f0 +# softirqs last disabled at (45569): [] __irq_exit_rcu+0xa1/0xc0 +# ---[ end trace 0000000000000000 ]--- +# Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 0 UID: 0 PID: 119 Comm: kworker/u8:6 Tainted: G W 6.13.0-rc2-ge95c88d68ac3 #1 +# Tainted: [W]=WARN +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffff9fb640efbd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff8e7241926000 RSI: ffff8e7241927ffc RDI: 000000000b7fb767 +# RBP: ffff9fb640efbde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff8e7241b09a80 R11: 0000000000000000 R12: ffff8e7241cd6200 +# R13: 0000000000000013 R14: 0000000000000000 R15: ffff8e7241b09a80 +# FS: 0000000000000000(0000) GS:ffff8e726bc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000118d1e000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x4a0 +# ? srso_return_thunk+0x5/0x5f +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x1a3/0x760 [vkms] +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x201/0x6c0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x320 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# +# Modules linked in: vkms +# CR2: 000000000000001c +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffff9fb640efbd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff8e7241926000 RSI: ffff8e7241927ffc RDI: 000000000b7fb767 +# RBP: ffff9fb640efbde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff8e7241b09a80 R11: 0000000000000000 R12: ffff8e7241cd6200 +# R13: 0000000000000013 R14: 0000000000000000 R15: ffff8e7241b09a80 +# FS: 0000000000000000(0000) GS:ffff8e726bc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000118d1e000 CR4: 0000000000350ef0 + +# DEBUG - Begin test kms_cursor_crc@cursor-rapid-movement-128x42 +# ------------[ cut here ]------------ +# WARNING: CPU: 0 PID: 2933 at drivers/gpu/drm/vkms/vkms_crtc.c:139 vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Modules linked in: vkms +# CPU: 0 UID: 0 PID: 2933 Comm: kms_cursor_crc Not tainted 6.13.0-rc2-g5219242748c8 #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# RIP: 0010:vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Code: f7 48 89 f3 e8 d0 bf 6e d0 48 8b 83 50 01 00 00 a8 01 75 15 48 8b bb a0 01 00 00 e8 59 05 15 d0 48 89 df 5b e9 50 05 15 d0 90 <0f> 0b 90 eb e5 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 +# RSP: 0018:ffffa14cc08b3b08 EFLAGS: 00010202 +# RAX: ffff9b864084b605 RBX: ffff9b8641ba4600 RCX: ffffffff91c96b65 +# RDX: ffffffff90ad1f80 RSI: 0000000000000000 RDI: 0000000000000000 +# RBP: 0000000000000000 R08: 0000000000000034 R09: 0000000000000002 +# R10: 0000000047dd15a5 R11: 00000000547dd15a R12: ffff9b864099c000 +# R13: 0000000000000000 R14: 00000000ffffffff R15: 0000000000000000 +# FS: 00007f4f437ab6c0(0000) GS:ffff9b866bc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 00007f4f44c3cd40 CR3: 0000000108c14000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __warn+0x8c/0x190 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? report_bug+0x164/0x190 +# ? handle_bug+0x54/0x90 +# ? exc_invalid_op+0x17/0x70 +# ? asm_exc_invalid_op+0x1a/0x20 +# ? __pfx_drm_property_free_blob+0x10/0x10 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? vkms_atomic_crtc_destroy_state+0x10/0x40 [vkms] +# drm_atomic_state_default_clear+0x137/0x2f0 +# __drm_atomic_state_free+0x6c/0xb0 +# drm_atomic_helper_update_plane+0x100/0x150 +# drm_mode_cursor_universal+0x10e/0x270 +# drm_mode_cursor_common+0x115/0x240 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# drm_mode_cursor_ioctl+0x4a/0x70 +# drm_ioctl_kernel+0xb0/0x110 +# drm_ioctl+0x235/0x4b0 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# __x64_sys_ioctl+0x92/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f4f44960c5b +# 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 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 +# RSP: 002b:00007ffcdfb0b560 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 0000000000000060 RCX: 00007f4f44960c5b +# RDX: 00007ffcdfb0b5f0 RSI: 00000000c01c64a3 RDI: 0000000000000005 +# RBP: 00007ffcdfb0b5f0 R08: 0000000000000007 R09: 000055c3a5801a30 +# R10: 3107764f00e1f281 R11: 0000000000000246 R12: 00000000c01c64a3 +# R13: 0000000000000005 R14: 000055c38b7e42c8 R15: 000055c3a579aab0 +# +# irq event stamp: 58747 +# hardirqs last enabled at (58753): [] __up_console_sem+0x4d/0x60 +# hardirqs last disabled at (58758): [] __up_console_sem+0x32/0x60 +# softirqs last enabled at (47324): [] handle_softirqs+0x310/0x3f0 +# softirqs last disabled at (47307): [] __irq_exit_rcu+0xa1/0xc0 +# ---[ end trace 0000000000000000 ]--- +# Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 1 UID: 0 PID: 11 Comm: kworker/u8:0 Tainted: G W 6.13.0-rc2-g5219242748c8 #1 +# Tainted: [W]=WARN +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa14cc005fd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff9b8669626000 RSI: ffff9b8669627ffc RDI: 00000000348d6c39 +# RBP: ffffa14cc005fde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff9b8645650eb0 R11: 0000000000000000 R12: ffff9b8641ba5800 +# R13: 0000000000000028 R14: 0000000000000000 R15: ffff9b8645650eb0 +# FS: 0000000000000000(0000) GS:ffff9b866bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000108c14000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x4a0 +# ? __kvmalloc_node_noprof+0x3e/0xc0 +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x1a3/0x760 [vkms] +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x201/0x6c0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x320 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# +# Modules linked in: vkms +# CR2: 000000000000001c +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa14cc005fd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff9b8669626000 RSI: ffff9b8669627ffc RDI: 00000000348d6c39 +# RBP: ffffa14cc005fde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff9b8645650eb0 R11: 0000000000000000 R12: ffff9b8641ba5800 +# R13: 0000000000000028 R14: 0000000000000000 R15: ffff9b8645650eb0 +# FS: 0000000000000000(0000) GS:ffff9b866bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000108c14000 CR4: 0000000000350ef0 + +# DEBUG - Begin test kms_cursor_crc@cursor-rapid-movement-32x32 +# ------------[ cut here ]------------ +# WARNING: CPU: 0 PID: 2933 at drivers/gpu/drm/vkms/vkms_crtc.c:139 vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Modules linked in: vkms +# CPU: 0 UID: 0 PID: 2933 Comm: kms_cursor_crc Not tainted 6.13.0-rc2-g5219242748c8 #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# RIP: 0010:vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Code: f7 48 89 f3 e8 d0 bf 6e d0 48 8b 83 50 01 00 00 a8 01 75 15 48 8b bb a0 01 00 00 e8 59 05 15 d0 48 89 df 5b e9 50 05 15 d0 90 <0f> 0b 90 eb e5 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 +# RSP: 0018:ffffa14cc08b3b08 EFLAGS: 00010202 +# RAX: ffff9b864084b605 RBX: ffff9b8641ba4600 RCX: ffffffff91c96b65 +# RDX: ffffffff90ad1f80 RSI: 0000000000000000 RDI: 0000000000000000 +# RBP: 0000000000000000 R08: 0000000000000034 R09: 0000000000000002 +# R10: 0000000047dd15a5 R11: 00000000547dd15a R12: ffff9b864099c000 +# R13: 0000000000000000 R14: 00000000ffffffff R15: 0000000000000000 +# FS: 00007f4f437ab6c0(0000) GS:ffff9b866bc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 00007f4f44c3cd40 CR3: 0000000108c14000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __warn+0x8c/0x190 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? report_bug+0x164/0x190 +# ? handle_bug+0x54/0x90 +# ? exc_invalid_op+0x17/0x70 +# ? asm_exc_invalid_op+0x1a/0x20 +# ? __pfx_drm_property_free_blob+0x10/0x10 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? vkms_atomic_crtc_destroy_state+0x10/0x40 [vkms] +# drm_atomic_state_default_clear+0x137/0x2f0 +# __drm_atomic_state_free+0x6c/0xb0 +# drm_atomic_helper_update_plane+0x100/0x150 +# drm_mode_cursor_universal+0x10e/0x270 +# drm_mode_cursor_common+0x115/0x240 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# drm_mode_cursor_ioctl+0x4a/0x70 +# drm_ioctl_kernel+0xb0/0x110 +# drm_ioctl+0x235/0x4b0 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# __x64_sys_ioctl+0x92/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f4f44960c5b +# 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 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 +# RSP: 002b:00007ffcdfb0b560 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 0000000000000060 RCX: 00007f4f44960c5b +# RDX: 00007ffcdfb0b5f0 RSI: 00000000c01c64a3 RDI: 0000000000000005 +# RBP: 00007ffcdfb0b5f0 R08: 0000000000000007 R09: 000055c3a5801a30 +# R10: 3107764f00e1f281 R11: 0000000000000246 R12: 00000000c01c64a3 +# R13: 0000000000000005 R14: 000055c38b7e42c8 R15: 000055c3a579aab0 +# +# irq event stamp: 58747 +# hardirqs last enabled at (58753): [] __up_console_sem+0x4d/0x60 +# hardirqs last disabled at (58758): [] __up_console_sem+0x32/0x60 +# softirqs last enabled at (47324): [] handle_softirqs+0x310/0x3f0 +# softirqs last disabled at (47307): [] __irq_exit_rcu+0xa1/0xc0 +# ---[ end trace 0000000000000000 ]--- +# Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 1 UID: 0 PID: 11 Comm: kworker/u8:0 Tainted: G W 6.13.0-rc2-g5219242748c8 #1 +# Tainted: [W]=WARN +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa14cc005fd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff9b8669626000 RSI: ffff9b8669627ffc RDI: 00000000348d6c39 +# RBP: ffffa14cc005fde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff9b8645650eb0 R11: 0000000000000000 R12: ffff9b8641ba5800 +# R13: 0000000000000028 R14: 0000000000000000 R15: ffff9b8645650eb0 +# FS: 0000000000000000(0000) GS:ffff9b866bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000108c14000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x4a0 +# ? __kvmalloc_node_noprof+0x3e/0xc0 +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x1a3/0x760 [vkms] +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x201/0x6c0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x320 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# +# Modules linked in: vkms +# CR2: 000000000000001c +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa14cc005fd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff9b8669626000 RSI: ffff9b8669627ffc RDI: 00000000348d6c39 +# RBP: ffffa14cc005fde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff9b8645650eb0 R11: 0000000000000000 R12: ffff9b8641ba5800 +# R13: 0000000000000028 R14: 0000000000000000 R15: ffff9b8645650eb0 +# FS: 0000000000000000(0000) GS:ffff9b866bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000108c14000 CR4: 0000000000350ef0 + +# DEBUG - Begin test kms_cursor_crc@cursor-rapid-movement-32x32 +# ------------[ cut here ]------------ +# WARNING: CPU: 0 PID: 2933 at drivers/gpu/drm/vkms/vkms_crtc.c:139 vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Modules linked in: vkms +# CPU: 0 UID: 0 PID: 2933 Comm: kms_cursor_crc Not tainted 6.13.0-rc2-g5219242748c8 #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# RIP: 0010:vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Code: f7 48 89 f3 e8 d0 bf 6e d0 48 8b 83 50 01 00 00 a8 01 75 15 48 8b bb a0 01 00 00 e8 59 05 15 d0 48 89 df 5b e9 50 05 15 d0 90 <0f> 0b 90 eb e5 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 +# RSP: 0018:ffffa14cc08b3b08 EFLAGS: 00010202 +# RAX: ffff9b864084b605 RBX: ffff9b8641ba4600 RCX: ffffffff91c96b65 +# RDX: ffffffff90ad1f80 RSI: 0000000000000000 RDI: 0000000000000000 +# RBP: 0000000000000000 R08: 0000000000000034 R09: 0000000000000002 +# R10: 0000000047dd15a5 R11: 00000000547dd15a R12: ffff9b864099c000 +# R13: 0000000000000000 R14: 00000000ffffffff R15: 0000000000000000 +# FS: 00007f4f437ab6c0(0000) GS:ffff9b866bc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 00007f4f44c3cd40 CR3: 0000000108c14000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __warn+0x8c/0x190 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? report_bug+0x164/0x190 +# ? handle_bug+0x54/0x90 +# ? exc_invalid_op+0x17/0x70 +# ? asm_exc_invalid_op+0x1a/0x20 +# ? __pfx_drm_property_free_blob+0x10/0x10 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? vkms_atomic_crtc_destroy_state+0x10/0x40 [vkms] +# drm_atomic_state_default_clear+0x137/0x2f0 +# __drm_atomic_state_free+0x6c/0xb0 +# drm_atomic_helper_update_plane+0x100/0x150 +# drm_mode_cursor_universal+0x10e/0x270 +# drm_mode_cursor_common+0x115/0x240 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# drm_mode_cursor_ioctl+0x4a/0x70 +# drm_ioctl_kernel+0xb0/0x110 +# drm_ioctl+0x235/0x4b0 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# __x64_sys_ioctl+0x92/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f4f44960c5b +# 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 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 +# RSP: 002b:00007ffcdfb0b560 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 0000000000000060 RCX: 00007f4f44960c5b +# RDX: 00007ffcdfb0b5f0 RSI: 00000000c01c64a3 RDI: 0000000000000005 +# RBP: 00007ffcdfb0b5f0 R08: 0000000000000007 R09: 000055c3a5801a30 +# R10: 3107764f00e1f281 R11: 0000000000000246 R12: 00000000c01c64a3 +# R13: 0000000000000005 R14: 000055c38b7e42c8 R15: 000055c3a579aab0 +# +# irq event stamp: 58747 +# hardirqs last enabled at (58753): [] __up_console_sem+0x4d/0x60 +# hardirqs last disabled at (58758): [] __up_console_sem+0x32/0x60 +# softirqs last enabled at (47324): [] handle_softirqs+0x310/0x3f0 +# softirqs last disabled at (47307): [] __irq_exit_rcu+0xa1/0xc0 +# ---[ end trace 0000000000000000 ]--- +# Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 1 UID: 0 PID: 11 Comm: kworker/u8:0 Tainted: G W 6.13.0-rc2-g5219242748c8 #1 +# Tainted: [W]=WARN +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa14cc005fd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff9b8669626000 RSI: ffff9b8669627ffc RDI: 00000000348d6c39 +# RBP: ffffa14cc005fde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff9b8645650eb0 R11: 0000000000000000 R12: ffff9b8641ba5800 +# R13: 0000000000000028 R14: 0000000000000000 R15: ffff9b8645650eb0 +# FS: 0000000000000000(0000) GS:ffff9b866bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000108c14000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x4a0 +# ? __kvmalloc_node_noprof+0x3e/0xc0 +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x1a3/0x760 [vkms] +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x201/0x6c0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x320 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# +# Modules linked in: vkms +# CR2: 000000000000001c +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa14cc005fd20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff9b8669626000 RSI: ffff9b8669627ffc RDI: 00000000348d6c39 +# RBP: ffffa14cc005fde0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff9b8645650eb0 R11: 0000000000000000 R12: ffff9b8641ba5800 +# R13: 0000000000000028 R14: 0000000000000000 R15: ffff9b8645650eb0 +# FS: 0000000000000000(0000) GS:ffff9b866bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000108c14000 CR4: 0000000000350ef0 + +# DEBUG - Begin test kms_cursor_crc@cursor-rapid-movement-128x128 +# ------------[ cut here ]------------ +# WARNING: CPU: 0 PID: 2898 at drivers/gpu/drm/vkms/vkms_crtc.c:139 vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Modules linked in: vkms +# CPU: 0 UID: 0 PID: 2898 Comm: kms_cursor_crc Not tainted 6.13.0-rc2-g1f006005ebf8 #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# RIP: 0010:vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# Code: f7 48 89 f3 e8 d0 bf 6e e1 48 8b 83 50 01 00 00 a8 01 75 15 48 8b bb a0 01 00 00 e8 59 05 15 e1 48 89 df 5b e9 50 05 15 e1 90 <0f> 0b 90 eb e5 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 +# RSP: 0018:ffffa35c4082fb08 EFLAGS: 00010202 +# RAX: ffff8b02c1c0f005 RBX: ffff8b02d4509600 RCX: ffffffffa2c96b65 +# RDX: ffffffffa1ad1f80 RSI: 0000000000000000 RDI: 0000000000000000 +# RBP: 0000000000000000 R08: 0000000000000034 R09: 0000000000000002 +# R10: 0000000030f11ddf R11: 00000000f30f11dd R12: ffff8b02d2528000 +# R13: 0000000000000000 R14: 00000000ffffffff R15: 0000000000000000 +# FS: 00007f4b071ab6c0(0000) GS:ffff8b02efc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000055f7f8384b48 CR3: 0000000104ef0000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __warn+0x8c/0x190 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? report_bug+0x164/0x190 +# ? handle_bug+0x54/0x90 +# ? exc_invalid_op+0x17/0x70 +# ? asm_exc_invalid_op+0x1a/0x20 +# ? __pfx_drm_property_free_blob+0x10/0x10 +# ? vkms_atomic_crtc_destroy_state+0x31/0x40 [vkms] +# ? vkms_atomic_crtc_destroy_state+0x10/0x40 [vkms] +# drm_atomic_state_default_clear+0x137/0x2f0 +# __drm_atomic_state_free+0x6c/0xb0 +# drm_atomic_helper_update_plane+0x100/0x150 +# drm_mode_cursor_universal+0x10e/0x270 +# drm_mode_cursor_common+0x115/0x240 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# drm_mode_cursor_ioctl+0x4a/0x70 +# drm_ioctl_kernel+0xb0/0x110 +# drm_ioctl+0x235/0x4b0 +# ? __pfx_drm_mode_cursor_ioctl+0x10/0x10 +# __x64_sys_ioctl+0x92/0xc0 +# do_syscall_64+0xbb/0x1d0 +# entry_SYSCALL_64_after_hwframe+0x77/0x7f +# RIP: 0033:0x7f4b0815ac5b +# 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 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 +# RSP: 002b:00007ffd726f75e0 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +# RAX: ffffffffffffffda RBX: 000000000000005d RCX: 00007f4b0815ac5b +# RDX: 00007ffd726f7670 RSI: 00000000c01c64a3 RDI: 0000000000000005 +# RBP: 00007ffd726f7670 R08: 0000000000000007 R09: 000055f7f83e30c0 +# R10: 2b16893c03bd381a R11: 0000000000000246 R12: 00000000c01c64a3 +# R13: 0000000000000005 R14: 000055f7dbee72c8 R15: 000055f7f837bab0 +# +# irq event stamp: 58921 +# hardirqs last enabled at (58927): [] __up_console_sem+0x4d/0x60 +# hardirqs last disabled at (58932): [] __up_console_sem+0x32/0x60 +# softirqs last enabled at (46140): [] handle_softirqs+0x310/0x3f0 +# softirqs last disabled at (46135): [] __irq_exit_rcu+0xa1/0xc0 +# ---[ end trace 0000000000000000 ]--- +# Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 1 UID: 0 PID: 1657 Comm: kworker/u8:14 Tainted: G W 6.13.0-rc2-g1f006005ebf8 #1 +# Tainted: [W]=WARN +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa35c40c43d20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff8b02c52c8000 RSI: ffff8b02c52c9ffc RDI: 00000000fa4761c9 +# RBP: ffffa35c40c43de0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff8b02c1c87840 R11: 0000000000000000 R12: ffff8b02d4508800 +# R13: 0000000000000021 R14: 0000000000000000 R15: ffff8b02c1c87840 +# FS: 0000000000000000(0000) GS:ffff8b02efd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 000000000000001c CR3: 0000000104ef0000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x4a0 +# ? srso_return_thunk+0x5/0x5f +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x1a3/0x760 [vkms] +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x201/0x6c0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x320 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# +# Modules linked in: vkms +# CR2: 000000000000001c +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x1a3/0x760 [vkms] +# Code: db 4d 89 fa 85 c9 0f 84 32 03 00 00 4d 8b 24 da 48 c7 44 24 60 00 00 00 00 48 c7 44 24 68 00 00 00 00 49 8b 84 24 48 01 00 00 <8b> 50 1c 44 39 ea 0f 8f f3 02 00 00 44 39 68 24 0f 8e e9 02 00 00 +# RSP: 0018:ffffa35c40c43d20 EFLAGS: 00010202 +# RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 +# RDX: ffff8b02c52c8000 RSI: ffff8b02c52c9ffc RDI: 00000000fa4761c9 +# RBP: ffffa35c40c43de0 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff8b02c1c87840 R11: 0000000000000000 R12: ffff8b02d4508800 +# R13: 0000000000000021 R14: 0000000000000000 R15: ffff8b02c1c87840 +# FS: 0000000000000000(0000) GS:ffff8b02efd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + # Skip driver specific tests ^amdgpu.* ^msm.* @@ -272,3 +802,8 @@ gem_.* i915_.* xe_.* tools_test.* + +# IGT issue. is_joiner_mode() should return false for non-Intel hardware. +# https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/162 +kms_display_modes@extended-mode-basic +kms_display_modes@mst-extended-mode-negative -- cgit v1.2.3-59-g8ed1b From 7a5cd45fab0a2671aa4ea6d8fb80cea268387176 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 14 Dec 2024 15:37:05 +0200 Subject: drm/encoder_slave: make mode_valid accept const struct drm_display_mode The mode_valid() callbacks of drm_encoder, drm_crtc and drm_bridge accept const struct drm_display_mode argument. Change the mode_valid callback of drm_encoder_slave to also accept const argument. Reviewed-by: Laurent Pinchart Reviewed-by: Lyude Paul Reviewed-by: Maxime Ripard Reviewed-by: Thomas Zimmermann Reviewed-by: Harry Wentland Link: https://patchwork.freedesktop.org/patch/msgid/20241214-drm-connector-mode-valid-const-v2-1-4f9498a4c822@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/i2c/ch7006_drv.c | 2 +- drivers/gpu/drm/i2c/sil164_drv.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 2 +- include/drm/drm_encoder_slave.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index fcb0fcd6c897..db4f95020fae 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -104,7 +104,7 @@ static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, } static int ch7006_encoder_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (ch7006_lookup_mode(encoder, mode)) return MODE_OK; diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index c17afa025d9d..6e5da2c5762f 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c @@ -255,7 +255,7 @@ sil164_encoder_restore(struct drm_encoder *encoder) static int sil164_encoder_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct sil164_priv *priv = to_sil164_priv(encoder); diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 3ecb101d23e9..35ad4e10d273 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -308,7 +308,7 @@ static int nv17_tv_get_modes(struct drm_encoder *encoder, } static int nv17_tv_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h index 49172166a164..b526643833dc 100644 --- a/include/drm/drm_encoder_slave.h +++ b/include/drm/drm_encoder_slave.h @@ -85,7 +85,7 @@ struct drm_encoder_slave_funcs { * @mode_valid: Analogous to &drm_encoder_helper_funcs @mode_valid. */ int (*mode_valid)(struct drm_encoder *encoder, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); /** * @mode_set: Analogous to &drm_encoder_helper_funcs @mode_set * callback. Wrapped by drm_i2c_encoder_mode_set(). -- cgit v1.2.3-59-g8ed1b From b255ce4388e09f14311e7912d0ccd45a14a08d66 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 14 Dec 2024 15:37:06 +0200 Subject: drm/amdgpu: don't change mode in amdgpu_dm_connector_mode_valid() Make amdgpu_dm_connector_mode_valid() duplicate the mode during the test rather than modifying the passed mode. This is a preparation to converting the mode_valid() callback of drm_connector to take a const struct drm_display_mode argument. Reviewed-by: Laurent Pinchart Reviewed-by: Maxime Ripard Reviewed-by: Thomas Zimmermann Reviewed-by: Harry Wentland Link: https://patchwork.freedesktop.org/patch/msgid/20241214-drm-connector-mode-valid-const-v2-2-4f9498a4c822@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index dea640816e19..f92ad3b77c19 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7420,6 +7420,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec { int result = MODE_ERROR; struct dc_sink *dc_sink; + struct drm_display_mode *test_mode; /* TODO: Unhardcode stream count */ struct dc_stream_state *stream; struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); @@ -7444,11 +7445,16 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec goto fail; } - drm_mode_set_crtcinfo(mode, 0); + test_mode = drm_mode_duplicate(connector->dev, mode); + if (!test_mode) + goto fail; + + drm_mode_set_crtcinfo(test_mode, 0); - stream = create_validate_stream_for_sink(aconnector, mode, + stream = create_validate_stream_for_sink(aconnector, test_mode, to_dm_connector_state(connector->state), NULL); + drm_mode_destroy(connector->dev, test_mode); if (stream) { dc_stream_release(stream); result = MODE_OK; -- cgit v1.2.3-59-g8ed1b From 5f011b442006ccb29044263df10843de80fc0b14 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 14 Dec 2024 15:37:07 +0200 Subject: drm/sti: hda: pass const struct drm_display_mode* to hda_get_mode_idx() Make hda_get_mode_idx() take a const struct drm_display_mode pointer instead of just raw struct drm_display_mode. This is a preparation to converting the mode_valid() callback of drm_connector to take a const struct drm_display_mode argument. Acked-by: Raphael Gallais-Pou Reviewed-by: Laurent Pinchart Reviewed-by: Maxime Ripard Reviewed-by: Thomas Zimmermann Reviewed-by: Harry Wentland Link: https://patchwork.freedesktop.org/patch/msgid/20241214-drm-connector-mode-valid-const-v2-3-4f9498a4c822@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/sti/sti_hda.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index b12863bea955..57aa260d1e46 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -280,12 +280,12 @@ static void hda_write(struct sti_hda *hda, u32 val, int offset) * * Return true if mode is found */ -static bool hda_get_mode_idx(struct drm_display_mode mode, int *idx) +static bool hda_get_mode_idx(const struct drm_display_mode *mode, int *idx) { unsigned int i; for (i = 0; i < ARRAY_SIZE(hda_supported_modes); i++) - if (drm_mode_equal(&hda_supported_modes[i].mode, &mode)) { + if (drm_mode_equal(&hda_supported_modes[i].mode, mode)) { *idx = i; return true; } @@ -443,7 +443,7 @@ static void sti_hda_pre_enable(struct drm_bridge *bridge) if (clk_prepare_enable(hda->clk_hddac)) DRM_ERROR("Failed to prepare/enable hda_hddac clk\n"); - if (!hda_get_mode_idx(hda->mode, &mode_idx)) { + if (!hda_get_mode_idx(&hda->mode, &mode_idx)) { DRM_ERROR("Undefined mode\n"); return; } @@ -526,7 +526,7 @@ static void sti_hda_set_mode(struct drm_bridge *bridge, drm_mode_copy(&hda->mode, mode); - if (!hda_get_mode_idx(hda->mode, &mode_idx)) { + if (!hda_get_mode_idx(&hda->mode, &mode_idx)) { DRM_ERROR("Undefined mode\n"); return; } @@ -614,7 +614,7 @@ sti_hda_connector_mode_valid(struct drm_connector *connector, = to_sti_hda_connector(connector); struct sti_hda *hda = hda_connector->hda; - if (!hda_get_mode_idx(*mode, &idx)) { + if (!hda_get_mode_idx(mode, &idx)) { return MODE_BAD; } else { result = clk_round_rate(hda->clk_pix, target); -- cgit v1.2.3-59-g8ed1b From 66df9debcb29d14802912ed79a9cf9ba721b51a4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 14 Dec 2024 15:37:08 +0200 Subject: drm/connector: make mode_valid_ctx take a const struct drm_display_mode The mode_valid() callbacks of drm_encoder, drm_crtc and drm_bridge take a const struct drm_display_mode argument. Change the mode_valid_ctx callback of drm_connector to also take a const argument. Acked-by: Jani Nikula Reviewed-by: Laurent Pinchart Reviewed-by: Maxime Ripard Reviewed-by: Thomas Zimmermann Reviewed-by: Harry Wentland Link: https://patchwork.freedesktop.org/patch/msgid/20241214-drm-connector-mode-valid-const-v2-4-4f9498a4c822@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +++--- include/drm/drm_modeset_helper_vtables.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 56ca571e534c..0812a3fd8b37 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1432,9 +1432,9 @@ static int intel_dp_mst_get_modes(struct drm_connector *connector) static int intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, - struct drm_display_mode *mode, - struct drm_modeset_acquire_ctx *ctx, - enum drm_mode_status *status) + const struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx, + enum drm_mode_status *status) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_connector *intel_connector = to_intel_connector(connector); diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index ec59015aec3c..fa9ee6a128be 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -1006,7 +1006,7 @@ struct drm_connector_helper_funcs { * */ int (*mode_valid_ctx)(struct drm_connector *connector, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct drm_modeset_acquire_ctx *ctx, enum drm_mode_status *status); -- cgit v1.2.3-59-g8ed1b From 26d6fd81916e62d2b0568d9756e5f9c33f0f9b7a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 14 Dec 2024 15:37:09 +0200 Subject: drm/connector: make mode_valid take a const struct drm_display_mode The mode_valid() callbacks of drm_encoder, drm_crtc and drm_bridge take a const struct drm_display_mode argument. Change the mode_valid callback of drm_connector to also take a const argument. Acked-by: Jani Nikula Reviewed-by: Liviu Dudau Reviewed-by: Raphael Gallais-Pou Reviewed-by: Laurent Pinchart Reviewed-by: Lyude Paul Reviewed-by: Maxime Ripard Reviewed-by: Thomas Zimmermann Reviewed-by: Harry Wentland Link: https://patchwork.freedesktop.org/patch/msgid/20241214-drm-connector-mode-valid-const-v2-5-4f9498a4c822@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 8 ++++---- drivers/gpu/drm/amd/amdgpu/atombios_dp.c | 2 +- drivers/gpu/drm/amd/amdgpu/atombios_dp.h | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c | 2 +- drivers/gpu/drm/arm/malidp_mw.c | 2 +- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 2 +- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 2 +- drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 7 ------- drivers/gpu/drm/display/drm_bridge_connector.c | 2 +- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 2 +- drivers/gpu/drm/drm_crtc_helper_internal.h | 2 +- drivers/gpu/drm/drm_probe_helper.c | 2 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 2 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 2 +- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 2 +- drivers/gpu/drm/gma500/psb_intel_drv.h | 2 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 2 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 2 +- drivers/gpu/drm/i915/display/dvo_ch7017.c | 2 +- drivers/gpu/drm/i915/display/dvo_ch7xxx.c | 2 +- drivers/gpu/drm/i915/display/dvo_ivch.c | 2 +- drivers/gpu/drm/i915/display/dvo_ns2501.c | 2 +- drivers/gpu/drm/i915/display/dvo_sil164.c | 2 +- drivers/gpu/drm/i915/display/dvo_tfp410.c | 2 +- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_crt.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi.h | 2 +- drivers/gpu/drm/i915/display/intel_dvo.c | 2 +- drivers/gpu/drm/i915/display/intel_dvo_dev.h | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +- drivers/gpu/drm/i915/display/intel_tv.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- drivers/gpu/drm/imx/ipuv3/imx-tve.c | 2 +- drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +- drivers/gpu/drm/qxl/qxl_display.c | 2 +- drivers/gpu/drm/radeon/atombios_dp.c | 2 +- drivers/gpu/drm/radeon/radeon_connectors.c | 10 +++++----- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- drivers/gpu/drm/rockchip/cdn-dp-core.c | 2 +- drivers/gpu/drm/rockchip/inno_hdmi.c | 4 ++-- drivers/gpu/drm/rockchip/rk3066_hdmi.c | 2 +- drivers/gpu/drm/sti/sti_dvo.c | 2 +- drivers/gpu/drm/sti/sti_hda.c | 2 +- drivers/gpu/drm/sti/sti_hdmi.c | 2 +- drivers/gpu/drm/tegra/dsi.c | 2 +- drivers/gpu/drm/tegra/hdmi.c | 2 +- drivers/gpu/drm/tegra/sor.c | 2 +- drivers/gpu/drm/vc4/vc4_txp.c | 2 +- drivers/gpu/drm/virtio/virtgpu_display.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 2 +- include/drm/display/drm_hdmi_state_helper.h | 2 +- include/drm/drm_modeset_helper_vtables.h | 2 +- 66 files changed, 73 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 344e0a9ee08a..5e375e9c4f5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -674,7 +674,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector) } static enum drm_mode_status amdgpu_connector_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); @@ -839,7 +839,7 @@ static int amdgpu_connector_vga_get_modes(struct drm_connector *connector) } static enum drm_mode_status amdgpu_connector_vga_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = drm_to_adev(dev); @@ -1196,7 +1196,7 @@ static void amdgpu_connector_dvi_force(struct drm_connector *connector) } static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = drm_to_adev(dev); @@ -1464,7 +1464,7 @@ out: } static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c index 622634c08c7b..521b9faab180 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c @@ -430,7 +430,7 @@ void amdgpu_atombios_dp_set_link_config(struct drm_connector *connector, } int amdgpu_atombios_dp_mode_valid_helper(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct amdgpu_connector_atom_dig *dig_connector; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.h b/drivers/gpu/drm/amd/amdgpu/atombios_dp.h index f59d85eaddf0..3e24acf8133f 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.h +++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.h @@ -32,7 +32,7 @@ int amdgpu_atombios_dp_get_panel_mode(struct drm_encoder *encoder, void amdgpu_atombios_dp_set_link_config(struct drm_connector *connector, const struct drm_display_mode *mode); int amdgpu_atombios_dp_mode_valid_helper(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); bool amdgpu_atombios_dp_needs_link_train(struct amdgpu_connector *amdgpu_connector); void amdgpu_atombios_dp_set_rx_power_state(struct drm_connector *connector, u8 power_state); 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 f92ad3b77c19..35c486ca74f6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7416,7 +7416,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, } enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int result = MODE_ERROR; struct dc_sink *dc_sink; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 6464a8378387..2cf9f6ca20bc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -945,7 +945,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, int link_index); enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c index ebccb74306a7..e075a6b317cc 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c @@ -88,7 +88,7 @@ komeda_wb_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status komeda_wb_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct drm_mode_config *mode_config = &dev->mode_config; diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index 2577f0cef8fc..600af5ad81b1 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -43,7 +43,7 @@ static int malidp_mw_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status malidp_mw_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct drm_mode_config *mode_config = &dev->mode_config; diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index eb5919b38263..fda66e7876b8 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -847,7 +847,7 @@ static int adv7511_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status adv7511_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct adv7511 *adv = connector_to_adv7511(connector); diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index d081850e3c03..25345c3274e3 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -1619,7 +1619,7 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device *mhdp, static enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn); 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 a3dcee62e7a5..a47aabf134fd 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -115,16 +115,9 @@ static int ge_b850v3_lvds_get_modes(struct drm_connector *connector) return num_modes; } -static enum drm_mode_status ge_b850v3_lvds_mode_valid( - struct drm_connector *connector, struct drm_display_mode *mode) -{ - return MODE_OK; -} - static const struct drm_connector_helper_funcs ge_b850v3_lvds_connector_helper_funcs = { .get_modes = ge_b850v3_lvds_get_modes, - .mode_valid = ge_b850v3_lvds_mode_valid, }; static enum drm_connector_status ge_b850v3_lvds_bridge_detect(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 32108307de66..0397e62f9cbc 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -327,7 +327,7 @@ static int drm_bridge_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status drm_bridge_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index cfc2aaee1da0..2691e8b3e480 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -539,7 +539,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); */ enum drm_mode_status drm_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { unsigned long long clock; diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h b/drivers/gpu/drm/drm_crtc_helper_internal.h index 8059f65c5d6c..bae73936acf9 100644 --- a/drivers/gpu/drm/drm_crtc_helper_internal.h +++ b/drivers/gpu/drm/drm_crtc_helper_internal.h @@ -43,7 +43,7 @@ enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode); int drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct drm_modeset_acquire_ctx *ctx, enum drm_mode_status *status); diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 96b266b37ba4..080b55200614 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -202,7 +202,7 @@ enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder, int drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct drm_modeset_acquire_ctx *ctx, enum drm_mode_status *status) { diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 176fd8871759..01813e11e6c6 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -931,7 +931,7 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) } static enum drm_mode_status hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct hdmi_context *hdata = connector_to_hdmi(connector); int ret; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index c418e8496bdf..84eff7519e32 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -63,7 +63,7 @@ static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->hdisplay & 0xf) return MODE_ERROR; diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 5a0acd914f76..06fe7480e7af 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -69,7 +69,7 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) } static enum drm_mode_status cdv_intel_crt_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index cc2ed9b3fd2d..53990d27c39f 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -505,7 +505,7 @@ static void cdv_intel_edp_backlight_off (struct gma_encoder *intel_encoder) static enum drm_mode_status cdv_intel_dp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct gma_encoder *encoder = gma_attached_encoder(connector); struct cdv_intel_dp *intel_dp = encoder->dev_priv; diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 2d95e0471291..f2a3e37ef632 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -222,7 +222,7 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector) } static enum drm_mode_status cdv_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 165000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index f3a4517bdf27..9276e3676ba0 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -153,7 +153,7 @@ static void cdv_intel_lvds_restore(struct drm_connector *connector) } static enum drm_mode_status cdv_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct drm_psb_private *dev_priv = to_drm_psb_private(dev); diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index ed8626c73541..1cf394369127 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -514,7 +514,7 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode) } static enum drm_mode_status oaktrail_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 165000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 2499fd6a80c9..9dc9dcd1b09f 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -212,7 +212,7 @@ extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern enum drm_mode_status psb_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); extern int psb_intel_lvds_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t value); diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index 138f153d38ba..9ad611b5956e 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -331,7 +331,7 @@ static void psb_intel_lvds_restore(struct drm_connector *connector) } enum drm_mode_status psb_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev); struct gma_encoder *gma_encoder = gma_attached_encoder(connector); diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 8dafff963ca8..afda40fc4494 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1159,7 +1159,7 @@ static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) } static enum drm_mode_status psb_intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); diff --git a/drivers/gpu/drm/i915/display/dvo_ch7017.c b/drivers/gpu/drm/i915/display/dvo_ch7017.c index 493e730c685b..206818f9ad49 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7017.c @@ -247,7 +247,7 @@ static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo) } static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 160000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c index 534b8544e0a4..10ab3cc73e58 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c @@ -276,7 +276,7 @@ static enum drm_connector_status ch7xxx_detect(struct intel_dvo_device *dvo) } static enum drm_mode_status ch7xxx_mode_valid(struct intel_dvo_device *dvo, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 165000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/i915/display/dvo_ivch.c b/drivers/gpu/drm/i915/display/dvo_ivch.c index 0d5cce6051b1..d9c3152d4338 100644 --- a/drivers/gpu/drm/i915/display/dvo_ivch.c +++ b/drivers/gpu/drm/i915/display/dvo_ivch.c @@ -314,7 +314,7 @@ static enum drm_connector_status ivch_detect(struct intel_dvo_device *dvo) } static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if (mode->clock > 112000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/i915/display/dvo_ns2501.c b/drivers/gpu/drm/i915/display/dvo_ns2501.c index 9d47f8a93e94..cb619ffc974f 100644 --- a/drivers/gpu/drm/i915/display/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/display/dvo_ns2501.c @@ -524,7 +524,7 @@ static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo) } static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { DRM_DEBUG_KMS ("is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n", diff --git a/drivers/gpu/drm/i915/display/dvo_sil164.c b/drivers/gpu/drm/i915/display/dvo_sil164.c index a8dd40c00997..b42c717085f3 100644 --- a/drivers/gpu/drm/i915/display/dvo_sil164.c +++ b/drivers/gpu/drm/i915/display/dvo_sil164.c @@ -189,7 +189,7 @@ static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo) } static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return MODE_OK; } diff --git a/drivers/gpu/drm/i915/display/dvo_tfp410.c b/drivers/gpu/drm/i915/display/dvo_tfp410.c index d9a0cd753a87..280699438526 100644 --- a/drivers/gpu/drm/i915/display/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/display/dvo_tfp410.c @@ -217,7 +217,7 @@ static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo) } static enum drm_mode_status tfp410_mode_valid(struct intel_dvo_device *dvo, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return MODE_OK; } diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 8a49f499e3fb..afe90cf0842a 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1459,7 +1459,7 @@ static void gen11_dsi_post_disable(struct intel_atomic_state *state, } static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_i915_private *i915 = to_i915(connector->dev); enum drm_mode_status status; diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 74c1983fe07e..69667cd49ec8 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -352,7 +352,7 @@ static void intel_enable_crt(struct intel_atomic_state *state, static enum drm_mode_status intel_crt_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_display *display = to_intel_display(connector->dev); struct drm_device *dev = connector->dev; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ff5ba7b3035f..ea4f775b12a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1371,7 +1371,7 @@ bool intel_dp_has_dsc(const struct intel_connector *connector) static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *_connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_connector *connector = to_intel_connector(_connector); struct intel_dp *intel_dp = intel_attached_dp(connector); diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index 0be46c6c9611..c93a3cf75c52 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -58,7 +58,7 @@ int intel_dsi_get_modes(struct drm_connector *connector) } enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_connector *intel_connector = to_intel_connector(connector); diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index e8ba4ccd99d3..89c7166a3860 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -165,7 +165,7 @@ enum drm_panel_orientation intel_dsi_get_panel_orientation(struct intel_connector *connector); int intel_dsi_get_modes(struct drm_connector *connector); enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi, const struct mipi_dsi_host_ops *funcs, enum port port); diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 2d5ffb37eac9..f425bea748c4 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -217,7 +217,7 @@ static void intel_enable_dvo(struct intel_atomic_state *state, static enum drm_mode_status intel_dvo_mode_valid(struct drm_connector *_connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_connector *connector = to_intel_connector(_connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_dvo_dev.h b/drivers/gpu/drm/i915/display/intel_dvo_dev.h index 4bf476656b8c..d20667870e50 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo_dev.h +++ b/drivers/gpu/drm/i915/display/intel_dvo_dev.h @@ -71,7 +71,7 @@ struct intel_dvo_dev_ops { * \return MODE_OK if the mode is valid, or another MODE_* otherwise. */ enum drm_mode_status (*mode_valid)(struct intel_dvo_device *dvo, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); /* * Callback for setting up a video mode after fixups have been made. diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index c6ce6bb88d7c..ae7600ea4a19 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2025,7 +2025,7 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, static enum drm_mode_status intel_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_display *display = to_intel_display(connector->dev); struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 6d7637ad980a..ef2f5c8948a7 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -389,7 +389,7 @@ static void intel_lvds_shutdown(struct intel_encoder *encoder) static enum drm_mode_status intel_lvds_mode_valid(struct drm_connector *_connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_connector *connector = to_intel_connector(_connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 7a28104f68ad..3dcb48879e81 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1938,7 +1938,7 @@ static void intel_enable_sdvo(struct intel_atomic_state *state, static enum drm_mode_status intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_i915_private *i915 = to_i915(connector->dev); struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector)); diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 27c530218ee6..fa2634aa574a 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -957,7 +957,7 @@ static const struct tv_mode *intel_tv_mode_find(const struct drm_connector_state static enum drm_mode_status intel_tv_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct intel_display *display = to_intel_display(connector->dev); struct drm_i915_private *i915 = to_i915(connector->dev); diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 9383eedee2d4..e7d9f5897d87 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1542,7 +1542,7 @@ static const struct drm_encoder_funcs intel_dsi_funcs = { }; static enum drm_mode_status vlv_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_i915_private *i915 = to_i915(connector->dev); diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c b/drivers/gpu/drm/imx/ipuv3/imx-tve.c index 3a3c8a195119..c5629e155d25 100644 --- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c +++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c @@ -217,7 +217,7 @@ static int imx_tve_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status imx_tve_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct imx_tve *tve = con_to_tve(connector); unsigned long rate; diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c index 7444b75c4215..52e728181b52 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c @@ -58,7 +58,7 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status mdp4_lvds_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 8097249612bc..2e09b5a6d155 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1142,7 +1142,7 @@ nv50_mstc_atomic_best_encoder(struct drm_connector *connector, static enum drm_mode_status nv50_mstc_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct nv50_mstc *mstc = nv50_mstc(connector); struct nouveau_encoder *outp = mstc->mstm->outp; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 8d5c9c74cbb9..2d26784bde74 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1074,7 +1074,7 @@ get_tmds_link_bandwidth(struct drm_connector *connector) static enum drm_mode_status nouveau_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index bc24af08dfcd..70aff64ced87 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -1044,7 +1044,7 @@ static int qxl_conn_get_modes(struct drm_connector *connector) } static enum drm_mode_status qxl_conn_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *ddev = connector->dev; struct qxl_device *qdev = to_qxl(ddev); diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 6328627b7c34..fa78824931cc 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -467,7 +467,7 @@ void radeon_dp_set_link_config(struct drm_connector *connector, } int radeon_dp_mode_valid_helper(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index f9996304d943..9f6a3df951ba 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -806,7 +806,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector) } static enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_encoder *encoder = radeon_best_single_encoder(connector); @@ -968,7 +968,7 @@ static int radeon_vga_get_modes(struct drm_connector *connector) } static enum drm_mode_status radeon_vga_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; @@ -1116,7 +1116,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector) } static enum drm_mode_status radeon_tv_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { if ((mode->hdisplay > 1024) || (mode->vdisplay > 768)) return MODE_CLOCK_RANGE; @@ -1447,7 +1447,7 @@ static void radeon_dvi_force(struct drm_connector *connector) } static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; @@ -1723,7 +1723,7 @@ out: } static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 4063d3801e81..3102f6c2d055 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -706,7 +706,7 @@ extern int radeon_get_monitor_bpc(struct drm_connector *connector); extern void radeon_connector_hotplug(struct drm_connector *connector); extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); extern void radeon_dp_set_link_config(struct drm_connector *connector, const struct drm_display_mode *mode); extern void radeon_dp_link_train(struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index b17de83b988b..292c31de18f1 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -275,7 +275,7 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status cdn_dp_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct cdn_dp_device *dp = connector_to_dp(connector); struct drm_display_info *display_info = &dp->connector.display_info; diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 898d90155057..483ecfeaebb0 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -471,7 +471,7 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, } static enum drm_mode_status inno_hdmi_display_mode_valid(struct inno_hdmi *hdmi, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { unsigned long mpixelclk, max_tolerance; long rounded_refclk; @@ -577,7 +577,7 @@ static int inno_hdmi_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status inno_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c index 403336397214..f7a460190313 100644 --- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c +++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c @@ -482,7 +482,7 @@ static int rk3066_hdmi_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status rk3066_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { u32 vic = drm_match_cea_mode(mode); diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index c6c2abaa1891..4dcddd02629b 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -349,7 +349,7 @@ static int sti_dvo_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status sti_dvo_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int target = mode->clock * 1000; int target_min = target - CLK_TOLERANCE_HZ; diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index 57aa260d1e46..14fdc00d2ba0 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -603,7 +603,7 @@ static int sti_hda_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status sti_hda_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int target = mode->clock * 1000; int target_min = target - CLK_TOLERANCE_HZ; diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index ca2fe17de4a5..164a34d793d8 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -1011,7 +1011,7 @@ fail: static enum drm_mode_status sti_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int target = mode->clock * 1000; int target_min = target - CLK_TOLERANCE_HZ; diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 4a8cd9ed0a94..9bb077558167 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -812,7 +812,7 @@ static const struct drm_connector_funcs tegra_dsi_connector_funcs = { static enum drm_mode_status tegra_dsi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return MODE_OK; } diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index e705f8590c13..8cd2969e7d4b 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -1137,7 +1137,7 @@ static const struct drm_connector_funcs tegra_hdmi_connector_funcs = { static enum drm_mode_status tegra_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct tegra_output *output = connector_to_output(connector); struct tegra_hdmi *hdmi = to_hdmi(output); diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 802d2db7007a..f98f70eda906 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -1789,7 +1789,7 @@ static int tegra_sor_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status tegra_sor_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { return MODE_OK; } diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 4eab069cda75..42acac05fe47 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -196,7 +196,7 @@ static int vc4_txp_connector_get_modes(struct drm_connector *connector) static enum drm_mode_status vc4_txp_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; struct drm_mode_config *mode_config = &dev->mode_config; diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 64baf2f22d9f..59a45e74a641 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -189,7 +189,7 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector) } static enum drm_mode_status virtio_gpu_conn_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { struct virtio_gpu_output *output = drm_connector_to_virtio_gpu_output(connector); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 8db38927729b..c896de07f7b0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2660,7 +2660,7 @@ out_unref: * Returns MODE_OK on success, or a drm_mode_status error code. */ enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { enum drm_mode_status ret; struct drm_device *dev = connector->dev; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 2a6c6d6581e0..4eab581883e2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -435,7 +435,7 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv, int increment, struct vmw_kms_dirty *dirty); enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); int vmw_connector_get_modes(struct drm_connector *connector); void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 114a75069e1c..f5d2ed1b0a72 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -839,7 +839,7 @@ static void vmw_stdu_connector_destroy(struct drm_connector *connector) static enum drm_mode_status vmw_stdu_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { enum drm_mode_status ret; struct drm_device *dev = connector->dev; diff --git a/include/drm/display/drm_hdmi_state_helper.h b/include/drm/display/drm_hdmi_state_helper.h index 9ae19f3caf72..dc2d1c48cc5b 100644 --- a/include/drm/display/drm_hdmi_state_helper.h +++ b/include/drm/display/drm_hdmi_state_helper.h @@ -27,6 +27,6 @@ void drm_atomic_helper_connector_hdmi_force(struct drm_connector *connector); enum drm_mode_status drm_hdmi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); #endif // DRM_HDMI_STATE_HELPER_H_ diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index fa9ee6a128be..b62f41f48962 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -967,7 +967,7 @@ struct drm_connector_helper_funcs { * drm_mode_status. */ enum drm_mode_status (*mode_valid)(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); /** * @mode_valid_ctx: -- cgit v1.2.3-59-g8ed1b From 9a0dfe9bacef9c3bf6aaa92b5913945364ef805f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 6 Jan 2025 01:00:13 +0200 Subject: drm/nouveau: incorporate I2C TV encoder drivers Chrontel CH7006 and Silicon Image sil164 drivers use drm_encoder_slave interface which is being used only by the nouveau driver. It doesn't make sense to keep this interface inside the DRM subsystem. In preparation to moving this set of helpers to the nouveau driver, move the only two I2C driver that use that interface to the nouveau driver too. Suggested-by: Laurent Pinchart Signed-off-by: Dmitry Baryshkov Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250106-nouveau-encoder-slave-v3-1-1d37d2f2c67f@linaro.org --- arch/arm/configs/multi_v7_defconfig | 4 +- arch/parisc/configs/generic-32bit_defconfig | 4 +- arch/parisc/configs/generic-64bit_defconfig | 4 +- drivers/gpu/drm/i2c/Kconfig | 18 - drivers/gpu/drm/i2c/Makefile | 6 - drivers/gpu/drm/i2c/ch7006_drv.c | 549 --------------------- drivers/gpu/drm/i2c/ch7006_mode.c | 470 ------------------ drivers/gpu/drm/i2c/ch7006_priv.h | 344 ------------- drivers/gpu/drm/i2c/sil164_drv.c | 451 ----------------- drivers/gpu/drm/nouveau/Kconfig | 18 + drivers/gpu/drm/nouveau/dispnv04/Kbuild | 2 + drivers/gpu/drm/nouveau/dispnv04/dfp.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/i2c/Kbuild | 5 + drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c | 549 +++++++++++++++++++++ drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c | 470 ++++++++++++++++++ drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h | 345 +++++++++++++ drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c | 452 +++++++++++++++++ drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | 2 +- .../gpu/drm/nouveau/include/dispnv04/i2c/ch7006.h | 87 ++++ .../gpu/drm/nouveau/include/dispnv04/i2c/sil164.h | 64 +++ include/drm/i2c/ch7006.h | 87 ---- include/drm/i2c/sil164.h | 64 --- 22 files changed, 2000 insertions(+), 1997 deletions(-) delete mode 100644 drivers/gpu/drm/i2c/ch7006_drv.c delete mode 100644 drivers/gpu/drm/i2c/ch7006_mode.c delete mode 100644 drivers/gpu/drm/i2c/ch7006_priv.h delete mode 100644 drivers/gpu/drm/i2c/sil164_drv.c create mode 100644 drivers/gpu/drm/nouveau/dispnv04/i2c/Kbuild create mode 100644 drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c create mode 100644 drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c create mode 100644 drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h create mode 100644 drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c create mode 100644 drivers/gpu/drm/nouveau/include/dispnv04/i2c/ch7006.h create mode 100644 drivers/gpu/drm/nouveau/include/dispnv04/i2c/sil164.h delete mode 100644 include/drm/i2c/ch7006.h delete mode 100644 include/drm/i2c/sil164.h (limited to 'drivers') diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 758276027dbc..4b100ddb0c54 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -713,10 +713,10 @@ CONFIG_VIDEO_ADV7604_CEC=y CONFIG_VIDEO_ML86V7667=m CONFIG_IMX_IPUV3_CORE=m CONFIG_DRM=y -# CONFIG_DRM_I2C_CH7006 is not set -# CONFIG_DRM_I2C_SIL164 is not set CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_NOUVEAU=m +# CONFIG_DRM_NOUVEAU_CH7006 is not set +# CONFIG_DRM_NOUVEAU_SIL164 is not set CONFIG_DRM_EXYNOS=m CONFIG_DRM_EXYNOS_FIMD=y CONFIG_DRM_EXYNOS_MIXER=y diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index 5ce258f3fffa..f5fffc24c3bc 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig @@ -132,11 +132,11 @@ CONFIG_I2C=y CONFIG_HWMON=m CONFIG_DRM=m CONFIG_DRM_DISPLAY_DP_AUX_CEC=y -# CONFIG_DRM_I2C_CH7006 is not set -# CONFIG_DRM_I2C_SIL164 is not set CONFIG_DRM_RADEON=m CONFIG_DRM_NOUVEAU=m # CONFIG_DRM_NOUVEAU_BACKLIGHT is not set +# CONFIG_DRM_NOUVEAU_CH7006 is not set +# CONFIG_DRM_NOUVEAU_SIL164 is not set CONFIG_DRM_VGEM=m CONFIG_DRM_UDL=m CONFIG_DRM_MGAG200=m diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig index 19a804860ed5..704f68fbf960 100644 --- a/arch/parisc/configs/generic-64bit_defconfig +++ b/arch/parisc/configs/generic-64bit_defconfig @@ -193,11 +193,11 @@ CONFIG_MEDIA_SUPPORT=m CONFIG_AGP=y CONFIG_AGP_PARISC=y CONFIG_DRM=y -# CONFIG_DRM_I2C_CH7006 is not set -# CONFIG_DRM_I2C_SIL164 is not set CONFIG_DRM_RADEON=y CONFIG_DRM_NOUVEAU=m # CONFIG_DRM_NOUVEAU_BACKLIGHT is not set +# CONFIG_DRM_NOUVEAU_CH7006 is not set +# CONFIG_DRM_NOUVEAU_SIL164 is not set CONFIG_DRM_MGAG200=m CONFIG_FB=y CONFIG_FB_PM2=m diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig index 6f19e1c35e30..d5200f67958e 100644 --- a/drivers/gpu/drm/i2c/Kconfig +++ b/drivers/gpu/drm/i2c/Kconfig @@ -2,24 +2,6 @@ menu "I2C encoder or helper chips" depends on DRM && DRM_KMS_HELPER && I2C -config DRM_I2C_CH7006 - tristate "Chrontel ch7006 TV encoder" - default m if DRM_NOUVEAU - help - Support for Chrontel ch7006 and similar TV encoders, found - on some nVidia video cards. - - This driver is currently only useful if you're also using - the nouveau driver. - -config DRM_I2C_SIL164 - tristate "Silicon Image sil164 TMDS transmitter" - default m if DRM_NOUVEAU - help - Support for sil164 and similar single-link (or dual-link - when used in pairs) TMDS transmitters, used in some nVidia - video cards. - config DRM_I2C_NXP_TDA998X tristate "NXP Semiconductors TDA998X HDMI encoder" default m if DRM_TILCDC diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index a962f6f08568..31fd35527d99 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -1,10 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -ch7006-y := ch7006_drv.o ch7006_mode.o -obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o - -sil164-y := sil164_drv.o -obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o - tda998x-y := tda998x_drv.o obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o obj-$(CONFIG_DRM_I2C_NXP_TDA9950) += tda9950.o diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c deleted file mode 100644 index db4f95020fae..000000000000 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (C) 2009 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 - -#include - -#include "ch7006_priv.h" - -/* DRM encoder functions */ - -static void ch7006_encoder_set_config(struct drm_encoder *encoder, - void *params) -{ - struct ch7006_priv *priv = to_ch7006_priv(encoder); - - priv->params = *(struct ch7006_encoder_params *)params; -} - -static void ch7006_encoder_destroy(struct drm_encoder *encoder) -{ - struct ch7006_priv *priv = to_ch7006_priv(encoder); - - drm_property_destroy(encoder->dev, priv->scale_property); - - kfree(priv); - to_encoder_slave(encoder)->slave_priv = NULL; - - drm_i2c_encoder_destroy(encoder); -} - -static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_state *state = &priv->state; - - ch7006_dbg(client, "\n"); - - if (mode == priv->last_dpms) - return; - priv->last_dpms = mode; - - ch7006_setup_power_state(encoder); - - ch7006_load_reg(client, state, CH7006_POWER); -} - -static void ch7006_encoder_save(struct drm_encoder *encoder) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - - ch7006_dbg(client, "\n"); - - ch7006_state_save(client, &priv->saved_state); -} - -static void ch7006_encoder_restore(struct drm_encoder *encoder) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - - ch7006_dbg(client, "\n"); - - ch7006_state_load(client, &priv->saved_state); -} - -static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct ch7006_priv *priv = to_ch7006_priv(encoder); - - /* The ch7006 is painfully picky with the input timings so no - * custom modes for now... */ - - priv->mode = ch7006_lookup_mode(encoder, mode); - - return !!priv->mode; -} - -static int ch7006_encoder_mode_valid(struct drm_encoder *encoder, - const struct drm_display_mode *mode) -{ - if (ch7006_lookup_mode(encoder, mode)) - return MODE_OK; - else - return MODE_BAD; -} - -static void ch7006_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *drm_mode, - struct drm_display_mode *adjusted_mode) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_encoder_params *params = &priv->params; - struct ch7006_state *state = &priv->state; - uint8_t *regs = state->regs; - const struct ch7006_mode *mode = priv->mode; - const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; - int start_active; - - ch7006_dbg(client, "\n"); - - regs[CH7006_DISPMODE] = norm->dispmode | mode->dispmode; - regs[CH7006_BWIDTH] = 0; - regs[CH7006_INPUT_FORMAT] = bitf(CH7006_INPUT_FORMAT_FORMAT, - params->input_format); - - regs[CH7006_CLKMODE] = CH7006_CLKMODE_SUBC_LOCK - | bitf(CH7006_CLKMODE_XCM, params->xcm) - | bitf(CH7006_CLKMODE_PCM, params->pcm); - if (params->clock_mode) - regs[CH7006_CLKMODE] |= CH7006_CLKMODE_MASTER; - if (params->clock_edge) - regs[CH7006_CLKMODE] |= CH7006_CLKMODE_POS_EDGE; - - start_active = (drm_mode->htotal & ~0x7) - (drm_mode->hsync_start & ~0x7); - regs[CH7006_POV] = bitf(CH7006_POV_START_ACTIVE_8, start_active); - regs[CH7006_START_ACTIVE] = bitf(CH7006_START_ACTIVE_0, start_active); - - regs[CH7006_INPUT_SYNC] = 0; - if (params->sync_direction) - regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_OUTPUT; - if (params->sync_encoding) - regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_EMBEDDED; - if (drm_mode->flags & DRM_MODE_FLAG_PVSYNC) - regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PVSYNC; - if (drm_mode->flags & DRM_MODE_FLAG_PHSYNC) - regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PHSYNC; - - regs[CH7006_DETECT] = 0; - regs[CH7006_BCLKOUT] = 0; - - regs[CH7006_SUBC_INC3] = 0; - if (params->pout_level) - regs[CH7006_SUBC_INC3] |= CH7006_SUBC_INC3_POUT_3_3V; - - regs[CH7006_SUBC_INC4] = 0; - if (params->active_detect) - regs[CH7006_SUBC_INC4] |= CH7006_SUBC_INC4_DS_INPUT; - - regs[CH7006_PLL_CONTROL] = priv->saved_state.regs[CH7006_PLL_CONTROL]; - - ch7006_setup_levels(encoder); - ch7006_setup_subcarrier(encoder); - ch7006_setup_pll(encoder); - ch7006_setup_power_state(encoder); - ch7006_setup_properties(encoder); - - ch7006_state_load(client, state); -} - -static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_state *state = &priv->state; - int det; - - ch7006_dbg(client, "\n"); - - ch7006_save_reg(client, state, CH7006_DETECT); - ch7006_save_reg(client, state, CH7006_POWER); - ch7006_save_reg(client, state, CH7006_CLKMODE); - - ch7006_write(client, CH7006_POWER, CH7006_POWER_RESET | - bitfs(CH7006_POWER_LEVEL, NORMAL)); - ch7006_write(client, CH7006_CLKMODE, CH7006_CLKMODE_MASTER); - - ch7006_write(client, CH7006_DETECT, CH7006_DETECT_SENSE); - - ch7006_write(client, CH7006_DETECT, 0); - - det = ch7006_read(client, CH7006_DETECT); - - ch7006_load_reg(client, state, CH7006_CLKMODE); - ch7006_load_reg(client, state, CH7006_POWER); - ch7006_load_reg(client, state, CH7006_DETECT); - - if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| - CH7006_DETECT_SVIDEO_C_TEST| - CH7006_DETECT_CVBS_TEST)) == 0) - priv->subconnector = DRM_MODE_SUBCONNECTOR_SCART; - else if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| - CH7006_DETECT_SVIDEO_C_TEST)) == 0) - priv->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; - else if ((det & CH7006_DETECT_CVBS_TEST) == 0) - priv->subconnector = DRM_MODE_SUBCONNECTOR_Composite; - else - priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; - - drm_object_property_set_value(&connector->base, - encoder->dev->mode_config.tv_subconnector_property, - priv->subconnector); - - return priv->subconnector ? connector_status_connected : - connector_status_disconnected; -} - -static int ch7006_encoder_get_modes(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - struct ch7006_priv *priv = to_ch7006_priv(encoder); - const struct ch7006_mode *mode; - int n = 0; - - for (mode = ch7006_modes; mode->mode.clock; mode++) { - if (~mode->valid_scales & 1<scale || - ~mode->valid_norms & 1<norm) - continue; - - drm_mode_probed_add(connector, - drm_mode_duplicate(encoder->dev, &mode->mode)); - - n++; - } - - return n; -} - -static int ch7006_encoder_create_resources(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct drm_device *dev = encoder->dev; - struct drm_mode_config *conf = &dev->mode_config; - - drm_mode_create_tv_properties_legacy(dev, NUM_TV_NORMS, ch7006_tv_norm_names); - - priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); - if (!priv->scale_property) - return -ENOMEM; - - drm_object_attach_property(&connector->base, conf->tv_select_subconnector_property, - priv->select_subconnector); - drm_object_attach_property(&connector->base, conf->tv_subconnector_property, - priv->subconnector); - drm_object_attach_property(&connector->base, conf->tv_left_margin_property, - priv->hmargin); - drm_object_attach_property(&connector->base, conf->tv_bottom_margin_property, - priv->vmargin); - drm_object_attach_property(&connector->base, conf->legacy_tv_mode_property, - priv->norm); - drm_object_attach_property(&connector->base, conf->tv_brightness_property, - priv->brightness); - drm_object_attach_property(&connector->base, conf->tv_contrast_property, - priv->contrast); - drm_object_attach_property(&connector->base, conf->tv_flicker_reduction_property, - priv->flicker); - drm_object_attach_property(&connector->base, priv->scale_property, - priv->scale); - - return 0; -} - -static int ch7006_encoder_set_property(struct drm_encoder *encoder, - struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_state *state = &priv->state; - struct drm_mode_config *conf = &encoder->dev->mode_config; - struct drm_crtc *crtc = encoder->crtc; - bool modes_changed = false; - - ch7006_dbg(client, "\n"); - - if (property == conf->tv_select_subconnector_property) { - priv->select_subconnector = val; - - ch7006_setup_power_state(encoder); - - ch7006_load_reg(client, state, CH7006_POWER); - - } else if (property == conf->tv_left_margin_property) { - priv->hmargin = val; - - ch7006_setup_properties(encoder); - - ch7006_load_reg(client, state, CH7006_POV); - ch7006_load_reg(client, state, CH7006_HPOS); - - } else if (property == conf->tv_bottom_margin_property) { - priv->vmargin = val; - - ch7006_setup_properties(encoder); - - ch7006_load_reg(client, state, CH7006_POV); - ch7006_load_reg(client, state, CH7006_VPOS); - - } else if (property == conf->legacy_tv_mode_property) { - if (connector->dpms != DRM_MODE_DPMS_OFF) - return -EINVAL; - - priv->norm = val; - - modes_changed = true; - - } else if (property == conf->tv_brightness_property) { - priv->brightness = val; - - ch7006_setup_levels(encoder); - - ch7006_load_reg(client, state, CH7006_BLACK_LEVEL); - - } else if (property == conf->tv_contrast_property) { - priv->contrast = val; - - ch7006_setup_properties(encoder); - - ch7006_load_reg(client, state, CH7006_CONTRAST); - - } else if (property == conf->tv_flicker_reduction_property) { - priv->flicker = val; - - ch7006_setup_properties(encoder); - - ch7006_load_reg(client, state, CH7006_FFILTER); - - } else if (property == priv->scale_property) { - if (connector->dpms != DRM_MODE_DPMS_OFF) - return -EINVAL; - - priv->scale = val; - - modes_changed = true; - - } else { - return -EINVAL; - } - - if (modes_changed) { - drm_helper_probe_single_connector_modes(connector, 0, 0); - - if (crtc) - drm_crtc_helper_set_mode(crtc, &crtc->mode, - crtc->x, crtc->y, - crtc->primary->fb); - } - - return 0; -} - -static const struct drm_encoder_slave_funcs ch7006_encoder_funcs = { - .set_config = ch7006_encoder_set_config, - .destroy = ch7006_encoder_destroy, - .dpms = ch7006_encoder_dpms, - .save = ch7006_encoder_save, - .restore = ch7006_encoder_restore, - .mode_fixup = ch7006_encoder_mode_fixup, - .mode_valid = ch7006_encoder_mode_valid, - .mode_set = ch7006_encoder_mode_set, - .detect = ch7006_encoder_detect, - .get_modes = ch7006_encoder_get_modes, - .create_resources = ch7006_encoder_create_resources, - .set_property = ch7006_encoder_set_property, -}; - - -/* I2C driver functions */ - -static int ch7006_probe(struct i2c_client *client) -{ - uint8_t addr = CH7006_VERSION_ID; - uint8_t val; - int ret; - - ch7006_dbg(client, "\n"); - - ret = i2c_master_send(client, &addr, sizeof(addr)); - if (ret < 0) - goto fail; - - ret = i2c_master_recv(client, &val, sizeof(val)); - if (ret < 0) - goto fail; - - ch7006_info(client, "Detected version ID: %x\n", val); - - /* I don't know what this is for, but otherwise I get no - * signal. - */ - ch7006_write(client, 0x3d, 0x0); - - return 0; - -fail: - ch7006_err(client, "Error %d reading version ID\n", ret); - - return -ENODEV; -} - -static void ch7006_remove(struct i2c_client *client) -{ - ch7006_dbg(client, "\n"); -} - -static int ch7006_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - ch7006_dbg(client, "\n"); - - ch7006_write(client, 0x3d, 0x0); - - return 0; -} - -static int ch7006_encoder_init(struct i2c_client *client, - struct drm_device *dev, - struct drm_encoder_slave *encoder) -{ - struct ch7006_priv *priv; - int i; - - ch7006_dbg(client, "\n"); - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - encoder->slave_priv = priv; - encoder->slave_funcs = &ch7006_encoder_funcs; - - priv->norm = TV_NORM_PAL; - priv->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic; - priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; - priv->scale = 1; - priv->contrast = 50; - priv->brightness = 50; - priv->flicker = 50; - priv->hmargin = 50; - priv->vmargin = 50; - priv->last_dpms = -1; - priv->chip_version = ch7006_read(client, CH7006_VERSION_ID); - - if (ch7006_tv_norm) { - for (i = 0; i < NUM_TV_NORMS; i++) { - if (!strcmp(ch7006_tv_norm_names[i], ch7006_tv_norm)) { - priv->norm = i; - break; - } - } - - if (i == NUM_TV_NORMS) - ch7006_err(client, "Invalid TV norm setting \"%s\".\n", - ch7006_tv_norm); - } - - if (ch7006_scale >= 0 && ch7006_scale <= 2) - priv->scale = ch7006_scale; - else - ch7006_err(client, "Invalid scale setting \"%d\".\n", - ch7006_scale); - - return 0; -} - -static const struct i2c_device_id ch7006_ids[] = { - { "ch7006" }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ch7006_ids); - -static const struct dev_pm_ops ch7006_pm_ops = { - .resume = ch7006_resume, -}; - -static struct drm_i2c_encoder_driver ch7006_driver = { - .i2c_driver = { - .probe = ch7006_probe, - .remove = ch7006_remove, - - .driver = { - .name = "ch7006", - .pm = &ch7006_pm_ops, - }, - - .id_table = ch7006_ids, - }, - - .encoder_init = ch7006_encoder_init, -}; - - -/* Module initialization */ - -static int __init ch7006_init(void) -{ - return drm_i2c_encoder_register(THIS_MODULE, &ch7006_driver); -} - -static void __exit ch7006_exit(void) -{ - drm_i2c_encoder_unregister(&ch7006_driver); -} - -int ch7006_debug; -module_param_named(debug, ch7006_debug, int, 0600); -MODULE_PARM_DESC(debug, "Enable debug output."); - -char *ch7006_tv_norm; -module_param_named(tv_norm, ch7006_tv_norm, charp, 0600); -MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" - "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, PAL-60, NTSC-M, NTSC-J.\n" - "\t\tDefault: PAL"); - -int ch7006_scale = 1; -module_param_named(scale, ch7006_scale, int, 0600); -MODULE_PARM_DESC(scale, "Default scale.\n" - "\t\tSupported: 0 -> Select video modes with a higher blanking ratio.\n" - "\t\t\t1 -> Select default video modes.\n" - "\t\t\t2 -> Select video modes with a lower blanking ratio."); - -MODULE_AUTHOR("Francisco Jerez "); -MODULE_DESCRIPTION("Chrontel ch7006 TV encoder driver"); -MODULE_LICENSE("GPL and additional rights"); - -module_init(ch7006_init); -module_exit(ch7006_exit); diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c deleted file mode 100644 index 6afe6d0ee630..000000000000 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 2009 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 "ch7006_priv.h" - -const char * const ch7006_tv_norm_names[] = { - [TV_NORM_PAL] = "PAL", - [TV_NORM_PAL_M] = "PAL-M", - [TV_NORM_PAL_N] = "PAL-N", - [TV_NORM_PAL_NC] = "PAL-Nc", - [TV_NORM_PAL_60] = "PAL-60", - [TV_NORM_NTSC_M] = "NTSC-M", - [TV_NORM_NTSC_J] = "NTSC-J", -}; - -#define NTSC_LIKE_TIMINGS .vrefresh = 60 * fixed1/1.001, \ - .vdisplay = 480, \ - .vtotal = 525, \ - .hvirtual = 660 - -#define PAL_LIKE_TIMINGS .vrefresh = 50 * fixed1, \ - .vdisplay = 576, \ - .vtotal = 625, \ - .hvirtual = 810 - -const struct ch7006_tv_norm_info ch7006_tv_norms[] = { - [TV_NORM_NTSC_M] = { - NTSC_LIKE_TIMINGS, - .black_level = 0.339 * fixed1, - .subc_freq = 3579545 * fixed1, - .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC), - .voffset = 0, - }, - [TV_NORM_NTSC_J] = { - NTSC_LIKE_TIMINGS, - .black_level = 0.286 * fixed1, - .subc_freq = 3579545 * fixed1, - .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC_J), - .voffset = 0, - }, - [TV_NORM_PAL] = { - PAL_LIKE_TIMINGS, - .black_level = 0.3 * fixed1, - .subc_freq = 4433618.75 * fixed1, - .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), - .voffset = 0, - }, - [TV_NORM_PAL_M] = { - NTSC_LIKE_TIMINGS, - .black_level = 0.339 * fixed1, - .subc_freq = 3575611.433 * fixed1, - .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M), - .voffset = 16, - }, - - /* The following modes seem to work right but they're - * undocumented */ - - [TV_NORM_PAL_N] = { - PAL_LIKE_TIMINGS, - .black_level = 0.339 * fixed1, - .subc_freq = 4433618.75 * fixed1, - .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), - .voffset = 0, - }, - [TV_NORM_PAL_NC] = { - PAL_LIKE_TIMINGS, - .black_level = 0.3 * fixed1, - .subc_freq = 3582056.25 * fixed1, - .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), - .voffset = 0, - }, - [TV_NORM_PAL_60] = { - NTSC_LIKE_TIMINGS, - .black_level = 0.3 * fixed1, - .subc_freq = 4433618.75 * fixed1, - .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M), - .voffset = 16, - }, -}; - -#define __MODE(f, hd, vd, ht, vt, hsynp, vsynp, \ - subc, scale, scale_mask, norm_mask, e_hd, e_vd) { \ - .mode = { \ - .name = #hd "x" #vd, \ - .status = 0, \ - .type = DRM_MODE_TYPE_DRIVER, \ - .clock = f, \ - .hdisplay = hd, \ - .hsync_start = e_hd + 16, \ - .hsync_end = e_hd + 80, \ - .htotal = ht, \ - .hskew = 0, \ - .vdisplay = vd, \ - .vsync_start = vd + 10, \ - .vsync_end = vd + 26, \ - .vtotal = vt, \ - .vscan = 0, \ - .flags = DRM_MODE_FLAG_##hsynp##HSYNC | \ - DRM_MODE_FLAG_##vsynp##VSYNC, \ - }, \ - .enc_hdisp = e_hd, \ - .enc_vdisp = e_vd, \ - .subc_coeff = subc * fixed1, \ - .dispmode = bitfs(CH7006_DISPMODE_SCALING_RATIO, scale) | \ - bitfs(CH7006_DISPMODE_INPUT_RES, e_hd##x##e_vd), \ - .valid_scales = scale_mask, \ - .valid_norms = norm_mask \ - } - -#define MODE(f, hd, vd, ht, vt, hsynp, vsynp, \ - subc, scale, scale_mask, norm_mask) \ - __MODE(f, hd, vd, ht, vt, hsynp, vsynp, subc, scale, \ - scale_mask, norm_mask, hd, vd) - -#define NTSC_LIKE (1 << TV_NORM_NTSC_M | 1 << TV_NORM_NTSC_J | \ - 1 << TV_NORM_PAL_M | 1 << TV_NORM_PAL_60) - -#define PAL_LIKE (1 << TV_NORM_PAL | 1 << TV_NORM_PAL_N | 1 << TV_NORM_PAL_NC) - -const struct ch7006_mode ch7006_modes[] = { - MODE(21000, 512, 384, 840, 500, N, N, 181.797557582, 5_4, 0x6, PAL_LIKE), - MODE(26250, 512, 384, 840, 625, N, N, 145.438046066, 1_1, 0x1, PAL_LIKE), - MODE(20140, 512, 384, 800, 420, N, N, 213.257083791, 5_4, 0x4, NTSC_LIKE), - MODE(24671, 512, 384, 784, 525, N, N, 174.0874153, 1_1, 0x3, NTSC_LIKE), - MODE(28125, 720, 400, 1125, 500, N, N, 135.742176298, 5_4, 0x6, PAL_LIKE), - MODE(34875, 720, 400, 1116, 625, N, N, 109.469496898, 1_1, 0x1, PAL_LIKE), - MODE(23790, 720, 400, 945, 420, N, N, 160.475642016, 5_4, 0x4, NTSC_LIKE), - MODE(29455, 720, 400, 936, 525, N, N, 129.614941843, 1_1, 0x3, NTSC_LIKE), - MODE(25000, 640, 400, 1000, 500, N, N, 152.709948279, 5_4, 0x6, PAL_LIKE), - MODE(31500, 640, 400, 1008, 625, N, N, 121.198371646, 1_1, 0x1, PAL_LIKE), - MODE(21147, 640, 400, 840, 420, N, N, 180.535097338, 5_4, 0x4, NTSC_LIKE), - MODE(26434, 640, 400, 840, 525, N, N, 144.42807787, 1_1, 0x2, NTSC_LIKE), - MODE(30210, 640, 400, 840, 600, N, N, 126.374568276, 7_8, 0x1, NTSC_LIKE), - MODE(21000, 640, 480, 840, 500, N, N, 181.797557582, 5_4, 0x4, PAL_LIKE), - MODE(26250, 640, 480, 840, 625, N, N, 145.438046066, 1_1, 0x2, PAL_LIKE), - MODE(31500, 640, 480, 840, 750, N, N, 121.198371646, 5_6, 0x1, PAL_LIKE), - MODE(24671, 640, 480, 784, 525, N, N, 174.0874153, 1_1, 0x4, NTSC_LIKE), - MODE(28196, 640, 480, 784, 600, N, N, 152.326488422, 7_8, 0x2, NTSC_LIKE), - MODE(30210, 640, 480, 800, 630, N, N, 142.171389101, 5_6, 0x1, NTSC_LIKE), - __MODE(29500, 720, 576, 944, 625, P, P, 145.592111636, 1_1, 0x7, PAL_LIKE, 800, 600), - MODE(36000, 800, 600, 960, 750, P, P, 119.304647022, 5_6, 0x6, PAL_LIKE), - MODE(39000, 800, 600, 936, 836, P, P, 110.127366499, 3_4, 0x1, PAL_LIKE), - MODE(39273, 800, 600, 1040, 630, P, P, 145.816809399, 5_6, 0x4, NTSC_LIKE), - MODE(43636, 800, 600, 1040, 700, P, P, 131.235128487, 3_4, 0x2, NTSC_LIKE), - MODE(47832, 800, 600, 1064, 750, P, P, 119.723275165, 7_10, 0x1, NTSC_LIKE), - {} -}; - -const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, - const struct drm_display_mode *drm_mode) -{ - struct ch7006_priv *priv = to_ch7006_priv(encoder); - const struct ch7006_mode *mode; - - for (mode = ch7006_modes; mode->mode.clock; mode++) { - - if (~mode->valid_norms & 1<norm) - continue; - - if (mode->mode.hdisplay != drm_mode->hdisplay || - mode->mode.vdisplay != drm_mode->vdisplay || - mode->mode.vtotal != drm_mode->vtotal || - mode->mode.htotal != drm_mode->htotal || - mode->mode.clock != drm_mode->clock) - continue; - - return mode; - } - - return NULL; -} - -/* Some common HW state calculation code */ - -void ch7006_setup_levels(struct drm_encoder *encoder) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - uint8_t *regs = priv->state.regs; - const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; - int gain; - int black_level; - - /* Set DAC_GAIN if the voltage drop between white and black is - * high enough. */ - if (norm->black_level < 339*fixed1/1000) { - gain = 76; - - regs[CH7006_INPUT_FORMAT] |= CH7006_INPUT_FORMAT_DAC_GAIN; - } else { - gain = 71; - - regs[CH7006_INPUT_FORMAT] &= ~CH7006_INPUT_FORMAT_DAC_GAIN; - } - - black_level = round_fixed(norm->black_level*26625)/gain; - - /* Correct it with the specified brightness. */ - black_level = interpolate(90, black_level, 208, priv->brightness); - - regs[CH7006_BLACK_LEVEL] = bitf(CH7006_BLACK_LEVEL_0, black_level); - - ch7006_dbg(client, "black level: %d\n", black_level); -} - -void ch7006_setup_subcarrier(struct drm_encoder *encoder) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_state *state = &priv->state; - const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; - const struct ch7006_mode *mode = priv->mode; - uint32_t subc_inc; - - subc_inc = round_fixed((mode->subc_coeff >> 8) - * (norm->subc_freq >> 24)); - - setbitf(state, CH7006_SUBC_INC0, 28, subc_inc); - setbitf(state, CH7006_SUBC_INC1, 24, subc_inc); - setbitf(state, CH7006_SUBC_INC2, 20, subc_inc); - setbitf(state, CH7006_SUBC_INC3, 16, subc_inc); - setbitf(state, CH7006_SUBC_INC4, 12, subc_inc); - setbitf(state, CH7006_SUBC_INC5, 8, subc_inc); - setbitf(state, CH7006_SUBC_INC6, 4, subc_inc); - setbitf(state, CH7006_SUBC_INC7, 0, subc_inc); - - ch7006_dbg(client, "subcarrier inc: %u\n", subc_inc); -} - -void ch7006_setup_pll(struct drm_encoder *encoder) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - uint8_t *regs = priv->state.regs; - const struct ch7006_mode *mode = priv->mode; - int n, best_n = 0; - int m, best_m = 0; - int freq, best_freq = 0; - - for (n = 0; n < CH7006_MAXN; n++) { - for (m = 0; m < CH7006_MAXM; m++) { - freq = CH7006_FREQ0*(n+2)/(m+2); - - if (abs(freq - mode->mode.clock) < - abs(best_freq - mode->mode.clock)) { - best_freq = freq; - best_n = n; - best_m = m; - } - } - } - - regs[CH7006_PLLOV] = bitf(CH7006_PLLOV_N_8, best_n) | - bitf(CH7006_PLLOV_M_8, best_m); - - regs[CH7006_PLLM] = bitf(CH7006_PLLM_0, best_m); - regs[CH7006_PLLN] = bitf(CH7006_PLLN_0, best_n); - - if (best_n < 108) - regs[CH7006_PLL_CONTROL] |= CH7006_PLL_CONTROL_CAPACITOR; - else - regs[CH7006_PLL_CONTROL] &= ~CH7006_PLL_CONTROL_CAPACITOR; - - ch7006_dbg(client, "n=%d m=%d f=%d c=%d\n", - best_n, best_m, best_freq, best_n < 108); -} - -void ch7006_setup_power_state(struct drm_encoder *encoder) -{ - struct ch7006_priv *priv = to_ch7006_priv(encoder); - uint8_t *power = &priv->state.regs[CH7006_POWER]; - int subconnector; - - subconnector = priv->select_subconnector ? priv->select_subconnector : - priv->subconnector; - - *power = CH7006_POWER_RESET; - - if (priv->last_dpms == DRM_MODE_DPMS_ON) { - switch (subconnector) { - case DRM_MODE_SUBCONNECTOR_SVIDEO: - *power |= bitfs(CH7006_POWER_LEVEL, CVBS_OFF); - break; - case DRM_MODE_SUBCONNECTOR_Composite: - *power |= bitfs(CH7006_POWER_LEVEL, SVIDEO_OFF); - break; - case DRM_MODE_SUBCONNECTOR_SCART: - *power |= bitfs(CH7006_POWER_LEVEL, NORMAL) | - CH7006_POWER_SCART; - break; - } - - } else { - if (priv->chip_version >= 0x20) - *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF); - else - *power |= bitfs(CH7006_POWER_LEVEL, POWER_OFF); - } -} - -void ch7006_setup_properties(struct drm_encoder *encoder) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_state *state = &priv->state; - const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; - const struct ch7006_mode *ch_mode = priv->mode; - const struct drm_display_mode *mode = &ch_mode->mode; - uint8_t *regs = state->regs; - int flicker, contrast, hpos, vpos; - uint64_t scale, aspect; - - flicker = interpolate(0, 2, 3, priv->flicker); - regs[CH7006_FFILTER] = bitf(CH7006_FFILTER_TEXT, flicker) | - bitf(CH7006_FFILTER_LUMA, flicker) | - bitf(CH7006_FFILTER_CHROMA, 1); - - contrast = interpolate(0, 5, 7, priv->contrast); - regs[CH7006_CONTRAST] = bitf(CH7006_CONTRAST_0, contrast); - - scale = norm->vtotal*fixed1; - do_div(scale, mode->vtotal); - - aspect = ch_mode->enc_hdisp*fixed1; - do_div(aspect, ch_mode->enc_vdisp); - - hpos = round_fixed((norm->hvirtual * aspect - mode->hdisplay * scale) - * priv->hmargin * mode->vtotal) / norm->vtotal / 100 / 4; - - setbitf(state, CH7006_POV, HPOS_8, hpos); - setbitf(state, CH7006_HPOS, 0, hpos); - - vpos = max(0, norm->vdisplay - round_fixed(mode->vdisplay*scale) - + norm->voffset) * priv->vmargin / 100 / 2; - - setbitf(state, CH7006_POV, VPOS_8, vpos); - setbitf(state, CH7006_VPOS, 0, vpos); - - ch7006_dbg(client, "hpos: %d, vpos: %d\n", hpos, vpos); -} - -/* HW access functions */ - -void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val) -{ - uint8_t buf[] = {addr, val}; - int ret; - - ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); - if (ret < 0) - ch7006_err(client, "Error %d writing to subaddress 0x%x\n", - ret, addr); -} - -uint8_t ch7006_read(struct i2c_client *client, uint8_t addr) -{ - uint8_t val; - int ret; - - ret = i2c_master_send(client, &addr, sizeof(addr)); - if (ret < 0) - goto fail; - - ret = i2c_master_recv(client, &val, sizeof(val)); - if (ret < 0) - goto fail; - - return val; - -fail: - ch7006_err(client, "Error %d reading from subaddress 0x%x\n", - ret, addr); - return 0; -} - -void ch7006_state_load(struct i2c_client *client, - struct ch7006_state *state) -{ - ch7006_load_reg(client, state, CH7006_POWER); - - ch7006_load_reg(client, state, CH7006_DISPMODE); - ch7006_load_reg(client, state, CH7006_FFILTER); - ch7006_load_reg(client, state, CH7006_BWIDTH); - ch7006_load_reg(client, state, CH7006_INPUT_FORMAT); - ch7006_load_reg(client, state, CH7006_CLKMODE); - ch7006_load_reg(client, state, CH7006_START_ACTIVE); - ch7006_load_reg(client, state, CH7006_POV); - ch7006_load_reg(client, state, CH7006_BLACK_LEVEL); - ch7006_load_reg(client, state, CH7006_HPOS); - ch7006_load_reg(client, state, CH7006_VPOS); - ch7006_load_reg(client, state, CH7006_INPUT_SYNC); - ch7006_load_reg(client, state, CH7006_DETECT); - ch7006_load_reg(client, state, CH7006_CONTRAST); - ch7006_load_reg(client, state, CH7006_PLLOV); - ch7006_load_reg(client, state, CH7006_PLLM); - ch7006_load_reg(client, state, CH7006_PLLN); - ch7006_load_reg(client, state, CH7006_BCLKOUT); - ch7006_load_reg(client, state, CH7006_SUBC_INC0); - ch7006_load_reg(client, state, CH7006_SUBC_INC1); - ch7006_load_reg(client, state, CH7006_SUBC_INC2); - ch7006_load_reg(client, state, CH7006_SUBC_INC3); - ch7006_load_reg(client, state, CH7006_SUBC_INC4); - ch7006_load_reg(client, state, CH7006_SUBC_INC5); - ch7006_load_reg(client, state, CH7006_SUBC_INC6); - ch7006_load_reg(client, state, CH7006_SUBC_INC7); - ch7006_load_reg(client, state, CH7006_PLL_CONTROL); - ch7006_load_reg(client, state, CH7006_CALC_SUBC_INC0); -} - -void ch7006_state_save(struct i2c_client *client, - struct ch7006_state *state) -{ - ch7006_save_reg(client, state, CH7006_POWER); - - ch7006_save_reg(client, state, CH7006_DISPMODE); - ch7006_save_reg(client, state, CH7006_FFILTER); - ch7006_save_reg(client, state, CH7006_BWIDTH); - ch7006_save_reg(client, state, CH7006_INPUT_FORMAT); - ch7006_save_reg(client, state, CH7006_CLKMODE); - ch7006_save_reg(client, state, CH7006_START_ACTIVE); - ch7006_save_reg(client, state, CH7006_POV); - ch7006_save_reg(client, state, CH7006_BLACK_LEVEL); - ch7006_save_reg(client, state, CH7006_HPOS); - ch7006_save_reg(client, state, CH7006_VPOS); - ch7006_save_reg(client, state, CH7006_INPUT_SYNC); - ch7006_save_reg(client, state, CH7006_DETECT); - ch7006_save_reg(client, state, CH7006_CONTRAST); - ch7006_save_reg(client, state, CH7006_PLLOV); - ch7006_save_reg(client, state, CH7006_PLLM); - ch7006_save_reg(client, state, CH7006_PLLN); - ch7006_save_reg(client, state, CH7006_BCLKOUT); - ch7006_save_reg(client, state, CH7006_SUBC_INC0); - ch7006_save_reg(client, state, CH7006_SUBC_INC1); - ch7006_save_reg(client, state, CH7006_SUBC_INC2); - ch7006_save_reg(client, state, CH7006_SUBC_INC3); - ch7006_save_reg(client, state, CH7006_SUBC_INC4); - ch7006_save_reg(client, state, CH7006_SUBC_INC5); - ch7006_save_reg(client, state, CH7006_SUBC_INC6); - ch7006_save_reg(client, state, CH7006_SUBC_INC7); - ch7006_save_reg(client, state, CH7006_PLL_CONTROL); - ch7006_save_reg(client, state, CH7006_CALC_SUBC_INC0); - - state->regs[CH7006_FFILTER] = (state->regs[CH7006_FFILTER] & 0xf0) | - (state->regs[CH7006_FFILTER] & 0x0c) >> 2 | - (state->regs[CH7006_FFILTER] & 0x03) << 2; -} diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h deleted file mode 100644 index 052bdc48a339..000000000000 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2009 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 __DRM_I2C_CH7006_PRIV_H__ -#define __DRM_I2C_CH7006_PRIV_H__ - -#include -#include -#include - -typedef int64_t fixed; -#define fixed1 (1LL << 32) - -enum ch7006_tv_norm { - TV_NORM_PAL, - TV_NORM_PAL_M, - TV_NORM_PAL_N, - TV_NORM_PAL_NC, - TV_NORM_PAL_60, - TV_NORM_NTSC_M, - TV_NORM_NTSC_J, - NUM_TV_NORMS -}; - -struct ch7006_tv_norm_info { - fixed vrefresh; - int vdisplay; - int vtotal; - int hvirtual; - - fixed subc_freq; - fixed black_level; - - uint32_t dispmode; - int voffset; -}; - -struct ch7006_mode { - struct drm_display_mode mode; - - int enc_hdisp; - int enc_vdisp; - - fixed subc_coeff; - uint32_t dispmode; - - uint32_t valid_scales; - uint32_t valid_norms; -}; - -struct ch7006_state { - uint8_t regs[0x26]; -}; - -struct ch7006_priv { - struct ch7006_encoder_params params; - const struct ch7006_mode *mode; - - struct ch7006_state state; - struct ch7006_state saved_state; - - struct drm_property *scale_property; - - int select_subconnector; - int subconnector; - int hmargin; - int vmargin; - enum ch7006_tv_norm norm; - int brightness; - int contrast; - int flicker; - int scale; - - int chip_version; - int last_dpms; -}; - -#define to_ch7006_priv(x) \ - ((struct ch7006_priv *)to_encoder_slave(x)->slave_priv) - -extern int ch7006_debug; -extern char *ch7006_tv_norm; -extern int ch7006_scale; - -extern const char * const ch7006_tv_norm_names[]; -extern const struct ch7006_tv_norm_info ch7006_tv_norms[]; -extern const struct ch7006_mode ch7006_modes[]; - -const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, - const struct drm_display_mode *drm_mode); - -void ch7006_setup_levels(struct drm_encoder *encoder); -void ch7006_setup_subcarrier(struct drm_encoder *encoder); -void ch7006_setup_pll(struct drm_encoder *encoder); -void ch7006_setup_power_state(struct drm_encoder *encoder); -void ch7006_setup_properties(struct drm_encoder *encoder); - -void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val); -uint8_t ch7006_read(struct i2c_client *client, uint8_t addr); - -void ch7006_state_load(struct i2c_client *client, - struct ch7006_state *state); -void ch7006_state_save(struct i2c_client *client, - struct ch7006_state *state); - -/* Some helper macros */ - -#define ch7006_dbg(client, format, ...) do { \ - if (ch7006_debug) \ - dev_printk(KERN_DEBUG, &client->dev, \ - "%s: " format, __func__, ## __VA_ARGS__); \ - } while (0) -#define ch7006_info(client, format, ...) \ - dev_info(&client->dev, format, __VA_ARGS__) -#define ch7006_err(client, format, ...) \ - dev_err(&client->dev, format, __VA_ARGS__) - -#define __mask(src, bitfield) \ - (((2 << (1 ? bitfield)) - 1) & ~((1 << (0 ? bitfield)) - 1)) -#define mask(bitfield) __mask(bitfield) - -#define __bitf(src, bitfield, x) \ - (((x) >> (src) << (0 ? bitfield)) & __mask(src, bitfield)) -#define bitf(bitfield, x) __bitf(bitfield, x) -#define bitfs(bitfield, s) __bitf(bitfield, bitfield##_##s) -#define setbitf(state, reg, bitfield, x) \ - state->regs[reg] = (state->regs[reg] & ~mask(reg##_##bitfield)) \ - | bitf(reg##_##bitfield, x) - -#define __unbitf(src, bitfield, x) \ - ((x & __mask(src, bitfield)) >> (0 ? bitfield) << (src)) -#define unbitf(bitfield, x) __unbitf(bitfield, x) - -static inline int interpolate(int y0, int y1, int y2, int x) -{ - return y1 + (x < 50 ? y1 - y0 : y2 - y1) * (x - 50) / 50; -} - -static inline int32_t round_fixed(fixed x) -{ - return (x + fixed1/2) >> 32; -} - -#define ch7006_load_reg(client, state, reg) ch7006_write(client, reg, state->regs[reg]) -#define ch7006_save_reg(client, state, reg) state->regs[reg] = ch7006_read(client, reg) - -/* Fixed hardware specs */ - -#define CH7006_FREQ0 14318 -#define CH7006_MAXN 650 -#define CH7006_MAXM 315 - -/* Register definitions */ - -#define CH7006_DISPMODE 0x00 -#define CH7006_DISPMODE_INPUT_RES 0, 7:5 -#define CH7006_DISPMODE_INPUT_RES_512x384 0x0 -#define CH7006_DISPMODE_INPUT_RES_720x400 0x1 -#define CH7006_DISPMODE_INPUT_RES_640x400 0x2 -#define CH7006_DISPMODE_INPUT_RES_640x480 0x3 -#define CH7006_DISPMODE_INPUT_RES_800x600 0x4 -#define CH7006_DISPMODE_INPUT_RES_NATIVE 0x5 -#define CH7006_DISPMODE_OUTPUT_STD 0, 4:3 -#define CH7006_DISPMODE_OUTPUT_STD_PAL 0x0 -#define CH7006_DISPMODE_OUTPUT_STD_NTSC 0x1 -#define CH7006_DISPMODE_OUTPUT_STD_PAL_M 0x2 -#define CH7006_DISPMODE_OUTPUT_STD_NTSC_J 0x3 -#define CH7006_DISPMODE_SCALING_RATIO 0, 2:0 -#define CH7006_DISPMODE_SCALING_RATIO_5_4 0x0 -#define CH7006_DISPMODE_SCALING_RATIO_1_1 0x1 -#define CH7006_DISPMODE_SCALING_RATIO_7_8 0x2 -#define CH7006_DISPMODE_SCALING_RATIO_5_6 0x3 -#define CH7006_DISPMODE_SCALING_RATIO_3_4 0x4 -#define CH7006_DISPMODE_SCALING_RATIO_7_10 0x5 - -#define CH7006_FFILTER 0x01 -#define CH7006_FFILTER_TEXT 0, 5:4 -#define CH7006_FFILTER_LUMA 0, 3:2 -#define CH7006_FFILTER_CHROMA 0, 1:0 -#define CH7006_FFILTER_CHROMA_NO_DCRAWL 0x3 - -#define CH7006_BWIDTH 0x03 -#define CH7006_BWIDTH_5L_FFILER (1 << 7) -#define CH7006_BWIDTH_CVBS_NO_CHROMA (1 << 6) -#define CH7006_BWIDTH_CHROMA 0, 5:4 -#define CH7006_BWIDTH_SVIDEO_YPEAK (1 << 3) -#define CH7006_BWIDTH_SVIDEO_LUMA 0, 2:1 -#define CH7006_BWIDTH_CVBS_LUMA 0, 0:0 - -#define CH7006_INPUT_FORMAT 0x04 -#define CH7006_INPUT_FORMAT_DAC_GAIN (1 << 6) -#define CH7006_INPUT_FORMAT_RGB_PASS_THROUGH (1 << 5) -#define CH7006_INPUT_FORMAT_FORMAT 0, 3:0 -#define CH7006_INPUT_FORMAT_FORMAT_RGB16 0x0 -#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m16 0x1 -#define CH7006_INPUT_FORMAT_FORMAT_RGB24m16 0x2 -#define CH7006_INPUT_FORMAT_FORMAT_RGB15 0x3 -#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12C 0x4 -#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12I 0x5 -#define CH7006_INPUT_FORMAT_FORMAT_RGB24m8 0x6 -#define CH7006_INPUT_FORMAT_FORMAT_RGB16m8 0x7 -#define CH7006_INPUT_FORMAT_FORMAT_RGB15m8 0x8 -#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m8 0x9 - -#define CH7006_CLKMODE 0x06 -#define CH7006_CLKMODE_SUBC_LOCK (1 << 7) -#define CH7006_CLKMODE_MASTER (1 << 6) -#define CH7006_CLKMODE_POS_EDGE (1 << 4) -#define CH7006_CLKMODE_XCM 0, 3:2 -#define CH7006_CLKMODE_PCM 0, 1:0 - -#define CH7006_START_ACTIVE 0x07 -#define CH7006_START_ACTIVE_0 0, 7:0 - -#define CH7006_POV 0x08 -#define CH7006_POV_START_ACTIVE_8 8, 2:2 -#define CH7006_POV_HPOS_8 8, 1:1 -#define CH7006_POV_VPOS_8 8, 0:0 - -#define CH7006_BLACK_LEVEL 0x09 -#define CH7006_BLACK_LEVEL_0 0, 7:0 - -#define CH7006_HPOS 0x0a -#define CH7006_HPOS_0 0, 7:0 - -#define CH7006_VPOS 0x0b -#define CH7006_VPOS_0 0, 7:0 - -#define CH7006_INPUT_SYNC 0x0d -#define CH7006_INPUT_SYNC_EMBEDDED (1 << 3) -#define CH7006_INPUT_SYNC_OUTPUT (1 << 2) -#define CH7006_INPUT_SYNC_PVSYNC (1 << 1) -#define CH7006_INPUT_SYNC_PHSYNC (1 << 0) - -#define CH7006_POWER 0x0e -#define CH7006_POWER_SCART (1 << 4) -#define CH7006_POWER_RESET (1 << 3) -#define CH7006_POWER_LEVEL 0, 2:0 -#define CH7006_POWER_LEVEL_CVBS_OFF 0x0 -#define CH7006_POWER_LEVEL_POWER_OFF 0x1 -#define CH7006_POWER_LEVEL_SVIDEO_OFF 0x2 -#define CH7006_POWER_LEVEL_NORMAL 0x3 -#define CH7006_POWER_LEVEL_FULL_POWER_OFF 0x4 - -#define CH7006_DETECT 0x10 -#define CH7006_DETECT_SVIDEO_Y_TEST (1 << 3) -#define CH7006_DETECT_SVIDEO_C_TEST (1 << 2) -#define CH7006_DETECT_CVBS_TEST (1 << 1) -#define CH7006_DETECT_SENSE (1 << 0) - -#define CH7006_CONTRAST 0x11 -#define CH7006_CONTRAST_0 0, 2:0 - -#define CH7006_PLLOV 0x13 -#define CH7006_PLLOV_N_8 8, 2:1 -#define CH7006_PLLOV_M_8 8, 0:0 - -#define CH7006_PLLM 0x14 -#define CH7006_PLLM_0 0, 7:0 - -#define CH7006_PLLN 0x15 -#define CH7006_PLLN_0 0, 7:0 - -#define CH7006_BCLKOUT 0x17 - -#define CH7006_SUBC_INC0 0x18 -#define CH7006_SUBC_INC0_28 28, 3:0 - -#define CH7006_SUBC_INC1 0x19 -#define CH7006_SUBC_INC1_24 24, 3:0 - -#define CH7006_SUBC_INC2 0x1a -#define CH7006_SUBC_INC2_20 20, 3:0 - -#define CH7006_SUBC_INC3 0x1b -#define CH7006_SUBC_INC3_GPIO1_VAL (1 << 7) -#define CH7006_SUBC_INC3_GPIO0_VAL (1 << 6) -#define CH7006_SUBC_INC3_POUT_3_3V (1 << 5) -#define CH7006_SUBC_INC3_POUT_INV (1 << 4) -#define CH7006_SUBC_INC3_16 16, 3:0 - -#define CH7006_SUBC_INC4 0x1c -#define CH7006_SUBC_INC4_GPIO1_IN (1 << 7) -#define CH7006_SUBC_INC4_GPIO0_IN (1 << 6) -#define CH7006_SUBC_INC4_DS_INPUT (1 << 4) -#define CH7006_SUBC_INC4_12 12, 3:0 - -#define CH7006_SUBC_INC5 0x1d -#define CH7006_SUBC_INC5_8 8, 3:0 - -#define CH7006_SUBC_INC6 0x1e -#define CH7006_SUBC_INC6_4 4, 3:0 - -#define CH7006_SUBC_INC7 0x1f -#define CH7006_SUBC_INC7_0 0, 3:0 - -#define CH7006_PLL_CONTROL 0x20 -#define CH7006_PLL_CONTROL_CPI (1 << 5) -#define CH7006_PLL_CONTROL_CAPACITOR (1 << 4) -#define CH7006_PLL_CONTROL_7STAGES (1 << 3) -#define CH7006_PLL_CONTROL_DIGITAL_5V (1 << 2) -#define CH7006_PLL_CONTROL_ANALOG_5V (1 << 1) -#define CH7006_PLL_CONTROL_MEMORY_5V (1 << 0) - -#define CH7006_CALC_SUBC_INC0 0x21 -#define CH7006_CALC_SUBC_INC0_24 24, 4:3 -#define CH7006_CALC_SUBC_INC0_HYST 0, 2:1 -#define CH7006_CALC_SUBC_INC0_AUTO (1 << 0) - -#define CH7006_CALC_SUBC_INC1 0x22 -#define CH7006_CALC_SUBC_INC1_16 16, 7:0 - -#define CH7006_CALC_SUBC_INC2 0x23 -#define CH7006_CALC_SUBC_INC2_8 8, 7:0 - -#define CH7006_CALC_SUBC_INC3 0x24 -#define CH7006_CALC_SUBC_INC3_0 0, 7:0 - -#define CH7006_VERSION_ID 0x25 - -#endif diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c deleted file mode 100644 index 6e5da2c5762f..000000000000 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (C) 2010 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 - -#include -#include -#include -#include -#include - -struct sil164_priv { - struct sil164_encoder_params config; - struct i2c_client *duallink_slave; - - uint8_t saved_state[0x10]; - uint8_t saved_slave_state[0x10]; -}; - -#define to_sil164_priv(x) \ - ((struct sil164_priv *)to_encoder_slave(x)->slave_priv) - -#define sil164_dbg(client, format, ...) do { \ - if (drm_debug_enabled(DRM_UT_KMS)) \ - dev_printk(KERN_DEBUG, &client->dev, \ - "%s: " format, __func__, ## __VA_ARGS__); \ - } while (0) -#define sil164_info(client, format, ...) \ - dev_info(&client->dev, format, __VA_ARGS__) -#define sil164_err(client, format, ...) \ - dev_err(&client->dev, format, __VA_ARGS__) - -#define SIL164_I2C_ADDR_MASTER 0x38 -#define SIL164_I2C_ADDR_SLAVE 0x39 - -/* HW register definitions */ - -#define SIL164_VENDOR_LO 0x0 -#define SIL164_VENDOR_HI 0x1 -#define SIL164_DEVICE_LO 0x2 -#define SIL164_DEVICE_HI 0x3 -#define SIL164_REVISION 0x4 -#define SIL164_FREQ_MIN 0x6 -#define SIL164_FREQ_MAX 0x7 -#define SIL164_CONTROL0 0x8 -# define SIL164_CONTROL0_POWER_ON 0x01 -# define SIL164_CONTROL0_EDGE_RISING 0x02 -# define SIL164_CONTROL0_INPUT_24BIT 0x04 -# define SIL164_CONTROL0_DUAL_EDGE 0x08 -# define SIL164_CONTROL0_HSYNC_ON 0x10 -# define SIL164_CONTROL0_VSYNC_ON 0x20 -#define SIL164_DETECT 0x9 -# define SIL164_DETECT_INTR_STAT 0x01 -# define SIL164_DETECT_HOTPLUG_STAT 0x02 -# define SIL164_DETECT_RECEIVER_STAT 0x04 -# define SIL164_DETECT_INTR_MODE_RECEIVER 0x00 -# define SIL164_DETECT_INTR_MODE_HOTPLUG 0x08 -# define SIL164_DETECT_OUT_MODE_HIGH 0x00 -# define SIL164_DETECT_OUT_MODE_INTR 0x10 -# define SIL164_DETECT_OUT_MODE_RECEIVER 0x20 -# define SIL164_DETECT_OUT_MODE_HOTPLUG 0x30 -# define SIL164_DETECT_VSWING_STAT 0x80 -#define SIL164_CONTROL1 0xa -# define SIL164_CONTROL1_DESKEW_ENABLE 0x10 -# define SIL164_CONTROL1_DESKEW_INCR_SHIFT 5 -#define SIL164_GPIO 0xb -#define SIL164_CONTROL2 0xc -# define SIL164_CONTROL2_FILTER_ENABLE 0x01 -# define SIL164_CONTROL2_FILTER_SETTING_SHIFT 1 -# define SIL164_CONTROL2_DUALLINK_MASTER 0x40 -# define SIL164_CONTROL2_SYNC_CONT 0x80 -#define SIL164_DUALLINK 0xd -# define SIL164_DUALLINK_ENABLE 0x10 -# define SIL164_DUALLINK_SKEW_SHIFT 5 -#define SIL164_PLLZONE 0xe -# define SIL164_PLLZONE_STAT 0x08 -# define SIL164_PLLZONE_FORCE_ON 0x10 -# define SIL164_PLLZONE_FORCE_HIGH 0x20 - -/* HW access functions */ - -static void -sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val) -{ - uint8_t buf[] = {addr, val}; - int ret; - - ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); - if (ret < 0) - sil164_err(client, "Error %d writing to subaddress 0x%x\n", - ret, addr); -} - -static uint8_t -sil164_read(struct i2c_client *client, uint8_t addr) -{ - uint8_t val; - int ret; - - ret = i2c_master_send(client, &addr, sizeof(addr)); - if (ret < 0) - goto fail; - - ret = i2c_master_recv(client, &val, sizeof(val)); - if (ret < 0) - goto fail; - - return val; - -fail: - sil164_err(client, "Error %d reading from subaddress 0x%x\n", - ret, addr); - return 0; -} - -static void -sil164_save_state(struct i2c_client *client, uint8_t *state) -{ - int i; - - for (i = 0x8; i <= 0xe; i++) - state[i] = sil164_read(client, i); -} - -static void -sil164_restore_state(struct i2c_client *client, uint8_t *state) -{ - int i; - - for (i = 0x8; i <= 0xe; i++) - sil164_write(client, i, state[i]); -} - -static void -sil164_set_power_state(struct i2c_client *client, bool on) -{ - uint8_t control0 = sil164_read(client, SIL164_CONTROL0); - - if (on) - control0 |= SIL164_CONTROL0_POWER_ON; - else - control0 &= ~SIL164_CONTROL0_POWER_ON; - - sil164_write(client, SIL164_CONTROL0, control0); -} - -static void -sil164_init_state(struct i2c_client *client, - struct sil164_encoder_params *config, - bool duallink) -{ - sil164_write(client, SIL164_CONTROL0, - SIL164_CONTROL0_HSYNC_ON | - SIL164_CONTROL0_VSYNC_ON | - (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) | - (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) | - (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0)); - - sil164_write(client, SIL164_DETECT, - SIL164_DETECT_INTR_STAT | - SIL164_DETECT_OUT_MODE_RECEIVER); - - sil164_write(client, SIL164_CONTROL1, - (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) | - (((config->input_skew + 4) & 0x7) - << SIL164_CONTROL1_DESKEW_INCR_SHIFT)); - - sil164_write(client, SIL164_CONTROL2, - SIL164_CONTROL2_SYNC_CONT | - (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) | - (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT)); - - sil164_write(client, SIL164_PLLZONE, 0); - - if (duallink) - sil164_write(client, SIL164_DUALLINK, - SIL164_DUALLINK_ENABLE | - (((config->duallink_skew + 4) & 0x7) - << SIL164_DUALLINK_SKEW_SHIFT)); - else - sil164_write(client, SIL164_DUALLINK, 0); -} - -/* DRM encoder functions */ - -static void -sil164_encoder_set_config(struct drm_encoder *encoder, void *params) -{ - struct sil164_priv *priv = to_sil164_priv(encoder); - - priv->config = *(struct sil164_encoder_params *)params; -} - -static void -sil164_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct sil164_priv *priv = to_sil164_priv(encoder); - bool on = (mode == DRM_MODE_DPMS_ON); - bool duallink = (on && encoder->crtc->mode.clock > 165000); - - sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on); - - if (priv->duallink_slave) - sil164_set_power_state(priv->duallink_slave, duallink); -} - -static void -sil164_encoder_save(struct drm_encoder *encoder) -{ - struct sil164_priv *priv = to_sil164_priv(encoder); - - sil164_save_state(drm_i2c_encoder_get_client(encoder), - priv->saved_state); - - if (priv->duallink_slave) - sil164_save_state(priv->duallink_slave, - priv->saved_slave_state); -} - -static void -sil164_encoder_restore(struct drm_encoder *encoder) -{ - struct sil164_priv *priv = to_sil164_priv(encoder); - - sil164_restore_state(drm_i2c_encoder_get_client(encoder), - priv->saved_state); - - if (priv->duallink_slave) - sil164_restore_state(priv->duallink_slave, - priv->saved_slave_state); -} - -static int -sil164_encoder_mode_valid(struct drm_encoder *encoder, - const struct drm_display_mode *mode) -{ - struct sil164_priv *priv = to_sil164_priv(encoder); - - if (mode->clock < 32000) - return MODE_CLOCK_LOW; - - if (mode->clock > 330000 || - (mode->clock > 165000 && !priv->duallink_slave)) - return MODE_CLOCK_HIGH; - - return MODE_OK; -} - -static void -sil164_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct sil164_priv *priv = to_sil164_priv(encoder); - bool duallink = adjusted_mode->clock > 165000; - - sil164_init_state(drm_i2c_encoder_get_client(encoder), - &priv->config, duallink); - - if (priv->duallink_slave) - sil164_init_state(priv->duallink_slave, - &priv->config, duallink); - - sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON); -} - -static enum drm_connector_status -sil164_encoder_detect(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - - if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT) - return connector_status_connected; - else - return connector_status_disconnected; -} - -static int -sil164_encoder_get_modes(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - return 0; -} - -static int -sil164_encoder_create_resources(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - return 0; -} - -static int -sil164_encoder_set_property(struct drm_encoder *encoder, - struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - return 0; -} - -static void -sil164_encoder_destroy(struct drm_encoder *encoder) -{ - struct sil164_priv *priv = to_sil164_priv(encoder); - - i2c_unregister_device(priv->duallink_slave); - - kfree(priv); - drm_i2c_encoder_destroy(encoder); -} - -static const struct drm_encoder_slave_funcs sil164_encoder_funcs = { - .set_config = sil164_encoder_set_config, - .destroy = sil164_encoder_destroy, - .dpms = sil164_encoder_dpms, - .save = sil164_encoder_save, - .restore = sil164_encoder_restore, - .mode_valid = sil164_encoder_mode_valid, - .mode_set = sil164_encoder_mode_set, - .detect = sil164_encoder_detect, - .get_modes = sil164_encoder_get_modes, - .create_resources = sil164_encoder_create_resources, - .set_property = sil164_encoder_set_property, -}; - -/* I2C driver functions */ - -static int -sil164_probe(struct i2c_client *client) -{ - int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 | - sil164_read(client, SIL164_VENDOR_LO); - int device = sil164_read(client, SIL164_DEVICE_HI) << 8 | - sil164_read(client, SIL164_DEVICE_LO); - int rev = sil164_read(client, SIL164_REVISION); - - if (vendor != 0x1 || device != 0x6) { - sil164_dbg(client, "Unknown device %x:%x.%x\n", - vendor, device, rev); - return -ENODEV; - } - - sil164_info(client, "Detected device %x:%x.%x\n", - vendor, device, rev); - - return 0; -} - -static struct i2c_client * -sil164_detect_slave(struct i2c_client *client) -{ - struct i2c_adapter *adap = client->adapter; - struct i2c_msg msg = { - .addr = SIL164_I2C_ADDR_SLAVE, - .len = 0, - }; - const struct i2c_board_info info = { - I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE) - }; - - if (i2c_transfer(adap, &msg, 1) != 1) { - sil164_dbg(adap, "No dual-link slave found."); - return NULL; - } - - return i2c_new_client_device(adap, &info); -} - -static int -sil164_encoder_init(struct i2c_client *client, - struct drm_device *dev, - struct drm_encoder_slave *encoder) -{ - struct sil164_priv *priv; - struct i2c_client *slave_client; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - encoder->slave_priv = priv; - encoder->slave_funcs = &sil164_encoder_funcs; - - slave_client = sil164_detect_slave(client); - if (!IS_ERR(slave_client)) - priv->duallink_slave = slave_client; - - return 0; -} - -static const struct i2c_device_id sil164_ids[] = { - { "sil164" }, - { } -}; -MODULE_DEVICE_TABLE(i2c, sil164_ids); - -static struct drm_i2c_encoder_driver sil164_driver = { - .i2c_driver = { - .probe = sil164_probe, - .driver = { - .name = "sil164", - }, - .id_table = sil164_ids, - }, - .encoder_init = sil164_encoder_init, -}; - -/* Module initialization */ - -static int __init -sil164_init(void) -{ - return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver); -} - -static void __exit -sil164_exit(void) -{ - drm_i2c_encoder_unregister(&sil164_driver); -} - -MODULE_AUTHOR("Francisco Jerez "); -MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver"); -MODULE_LICENSE("GPL and additional rights"); - -module_init(sil164_init); -module_exit(sil164_exit); diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index ce840300578d..ac76c0787010 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -109,3 +109,21 @@ config DRM_NOUVEAU_GSP_DEFAULT help Say Y here if you want to use the GSP codepaths by default on Turing and Ampere GPUs. + +config DRM_NOUVEAU_CH7006 + tristate "Chrontel ch7006 TV encoder" + depends on DRM_NOUVEAU + default m + help + Support for Chrontel ch7006 and similar TV encoders. + + This driver is currently only useful if you're also using + the nouveau driver. + +config DRM_NOUVEAU_SIL164 + tristate "Silicon Image sil164 TMDS transmitter" + depends on DRM_NOUVEAU + default m + help + Support for sil164 and similar single-link (or dual-link + when used in pairs) TMDS transmitters. diff --git a/drivers/gpu/drm/nouveau/dispnv04/Kbuild b/drivers/gpu/drm/nouveau/dispnv04/Kbuild index 975c4e226936..949802882ebd 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/Kbuild +++ b/drivers/gpu/drm/nouveau/dispnv04/Kbuild @@ -10,3 +10,5 @@ nouveau-y += dispnv04/overlay.o nouveau-y += dispnv04/tvmodesnv17.o nouveau-y += dispnv04/tvnv04.o nouveau-y += dispnv04/tvnv17.o + +include $(src)/dispnv04/i2c/Kbuild diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 504c421aa176..25fa41edcb3c 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -35,7 +35,7 @@ #include "hw.h" #include "nvreg.h" -#include +#include #include diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/Kbuild b/drivers/gpu/drm/nouveau/dispnv04/i2c/Kbuild new file mode 100644 index 000000000000..3fddfc97bcb3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/Kbuild @@ -0,0 +1,5 @@ +ch7006-y := dispnv04/i2c/ch7006_drv.o dispnv04/i2c/ch7006_mode.o +obj-$(CONFIG_DRM_NOUVEAU_CH7006) += ch7006.o + +sil164-y := dispnv04/i2c/sil164_drv.o +obj-$(CONFIG_DRM_NOUVEAU_SIL164) += sil164.o diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c new file mode 100644 index 000000000000..db4f95020fae --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 + +#include + +#include "ch7006_priv.h" + +/* DRM encoder functions */ + +static void ch7006_encoder_set_config(struct drm_encoder *encoder, + void *params) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + priv->params = *(struct ch7006_encoder_params *)params; +} + +static void ch7006_encoder_destroy(struct drm_encoder *encoder) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + drm_property_destroy(encoder->dev, priv->scale_property); + + kfree(priv); + to_encoder_slave(encoder)->slave_priv = NULL; + + drm_i2c_encoder_destroy(encoder); +} + +static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + + ch7006_dbg(client, "\n"); + + if (mode == priv->last_dpms) + return; + priv->last_dpms = mode; + + ch7006_setup_power_state(encoder); + + ch7006_load_reg(client, state, CH7006_POWER); +} + +static void ch7006_encoder_save(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + ch7006_dbg(client, "\n"); + + ch7006_state_save(client, &priv->saved_state); +} + +static void ch7006_encoder_restore(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + ch7006_dbg(client, "\n"); + + ch7006_state_load(client, &priv->saved_state); +} + +static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + + /* The ch7006 is painfully picky with the input timings so no + * custom modes for now... */ + + priv->mode = ch7006_lookup_mode(encoder, mode); + + return !!priv->mode; +} + +static int ch7006_encoder_mode_valid(struct drm_encoder *encoder, + const struct drm_display_mode *mode) +{ + if (ch7006_lookup_mode(encoder, mode)) + return MODE_OK; + else + return MODE_BAD; +} + +static void ch7006_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *drm_mode, + struct drm_display_mode *adjusted_mode) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_encoder_params *params = &priv->params; + struct ch7006_state *state = &priv->state; + uint8_t *regs = state->regs; + const struct ch7006_mode *mode = priv->mode; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + int start_active; + + ch7006_dbg(client, "\n"); + + regs[CH7006_DISPMODE] = norm->dispmode | mode->dispmode; + regs[CH7006_BWIDTH] = 0; + regs[CH7006_INPUT_FORMAT] = bitf(CH7006_INPUT_FORMAT_FORMAT, + params->input_format); + + regs[CH7006_CLKMODE] = CH7006_CLKMODE_SUBC_LOCK + | bitf(CH7006_CLKMODE_XCM, params->xcm) + | bitf(CH7006_CLKMODE_PCM, params->pcm); + if (params->clock_mode) + regs[CH7006_CLKMODE] |= CH7006_CLKMODE_MASTER; + if (params->clock_edge) + regs[CH7006_CLKMODE] |= CH7006_CLKMODE_POS_EDGE; + + start_active = (drm_mode->htotal & ~0x7) - (drm_mode->hsync_start & ~0x7); + regs[CH7006_POV] = bitf(CH7006_POV_START_ACTIVE_8, start_active); + regs[CH7006_START_ACTIVE] = bitf(CH7006_START_ACTIVE_0, start_active); + + regs[CH7006_INPUT_SYNC] = 0; + if (params->sync_direction) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_OUTPUT; + if (params->sync_encoding) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_EMBEDDED; + if (drm_mode->flags & DRM_MODE_FLAG_PVSYNC) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PVSYNC; + if (drm_mode->flags & DRM_MODE_FLAG_PHSYNC) + regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PHSYNC; + + regs[CH7006_DETECT] = 0; + regs[CH7006_BCLKOUT] = 0; + + regs[CH7006_SUBC_INC3] = 0; + if (params->pout_level) + regs[CH7006_SUBC_INC3] |= CH7006_SUBC_INC3_POUT_3_3V; + + regs[CH7006_SUBC_INC4] = 0; + if (params->active_detect) + regs[CH7006_SUBC_INC4] |= CH7006_SUBC_INC4_DS_INPUT; + + regs[CH7006_PLL_CONTROL] = priv->saved_state.regs[CH7006_PLL_CONTROL]; + + ch7006_setup_levels(encoder); + ch7006_setup_subcarrier(encoder); + ch7006_setup_pll(encoder); + ch7006_setup_power_state(encoder); + ch7006_setup_properties(encoder); + + ch7006_state_load(client, state); +} + +static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + int det; + + ch7006_dbg(client, "\n"); + + ch7006_save_reg(client, state, CH7006_DETECT); + ch7006_save_reg(client, state, CH7006_POWER); + ch7006_save_reg(client, state, CH7006_CLKMODE); + + ch7006_write(client, CH7006_POWER, CH7006_POWER_RESET | + bitfs(CH7006_POWER_LEVEL, NORMAL)); + ch7006_write(client, CH7006_CLKMODE, CH7006_CLKMODE_MASTER); + + ch7006_write(client, CH7006_DETECT, CH7006_DETECT_SENSE); + + ch7006_write(client, CH7006_DETECT, 0); + + det = ch7006_read(client, CH7006_DETECT); + + ch7006_load_reg(client, state, CH7006_CLKMODE); + ch7006_load_reg(client, state, CH7006_POWER); + ch7006_load_reg(client, state, CH7006_DETECT); + + if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| + CH7006_DETECT_SVIDEO_C_TEST| + CH7006_DETECT_CVBS_TEST)) == 0) + priv->subconnector = DRM_MODE_SUBCONNECTOR_SCART; + else if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| + CH7006_DETECT_SVIDEO_C_TEST)) == 0) + priv->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; + else if ((det & CH7006_DETECT_CVBS_TEST) == 0) + priv->subconnector = DRM_MODE_SUBCONNECTOR_Composite; + else + priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + + drm_object_property_set_value(&connector->base, + encoder->dev->mode_config.tv_subconnector_property, + priv->subconnector); + + return priv->subconnector ? connector_status_connected : + connector_status_disconnected; +} + +static int ch7006_encoder_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + const struct ch7006_mode *mode; + int n = 0; + + for (mode = ch7006_modes; mode->mode.clock; mode++) { + if (~mode->valid_scales & 1<scale || + ~mode->valid_norms & 1<norm) + continue; + + drm_mode_probed_add(connector, + drm_mode_duplicate(encoder->dev, &mode->mode)); + + n++; + } + + return n; +} + +static int ch7006_encoder_create_resources(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct drm_device *dev = encoder->dev; + struct drm_mode_config *conf = &dev->mode_config; + + drm_mode_create_tv_properties_legacy(dev, NUM_TV_NORMS, ch7006_tv_norm_names); + + priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); + if (!priv->scale_property) + return -ENOMEM; + + drm_object_attach_property(&connector->base, conf->tv_select_subconnector_property, + priv->select_subconnector); + drm_object_attach_property(&connector->base, conf->tv_subconnector_property, + priv->subconnector); + drm_object_attach_property(&connector->base, conf->tv_left_margin_property, + priv->hmargin); + drm_object_attach_property(&connector->base, conf->tv_bottom_margin_property, + priv->vmargin); + drm_object_attach_property(&connector->base, conf->legacy_tv_mode_property, + priv->norm); + drm_object_attach_property(&connector->base, conf->tv_brightness_property, + priv->brightness); + drm_object_attach_property(&connector->base, conf->tv_contrast_property, + priv->contrast); + drm_object_attach_property(&connector->base, conf->tv_flicker_reduction_property, + priv->flicker); + drm_object_attach_property(&connector->base, priv->scale_property, + priv->scale); + + return 0; +} + +static int ch7006_encoder_set_property(struct drm_encoder *encoder, + struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + struct drm_mode_config *conf = &encoder->dev->mode_config; + struct drm_crtc *crtc = encoder->crtc; + bool modes_changed = false; + + ch7006_dbg(client, "\n"); + + if (property == conf->tv_select_subconnector_property) { + priv->select_subconnector = val; + + ch7006_setup_power_state(encoder); + + ch7006_load_reg(client, state, CH7006_POWER); + + } else if (property == conf->tv_left_margin_property) { + priv->hmargin = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_POV); + ch7006_load_reg(client, state, CH7006_HPOS); + + } else if (property == conf->tv_bottom_margin_property) { + priv->vmargin = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_POV); + ch7006_load_reg(client, state, CH7006_VPOS); + + } else if (property == conf->legacy_tv_mode_property) { + if (connector->dpms != DRM_MODE_DPMS_OFF) + return -EINVAL; + + priv->norm = val; + + modes_changed = true; + + } else if (property == conf->tv_brightness_property) { + priv->brightness = val; + + ch7006_setup_levels(encoder); + + ch7006_load_reg(client, state, CH7006_BLACK_LEVEL); + + } else if (property == conf->tv_contrast_property) { + priv->contrast = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_CONTRAST); + + } else if (property == conf->tv_flicker_reduction_property) { + priv->flicker = val; + + ch7006_setup_properties(encoder); + + ch7006_load_reg(client, state, CH7006_FFILTER); + + } else if (property == priv->scale_property) { + if (connector->dpms != DRM_MODE_DPMS_OFF) + return -EINVAL; + + priv->scale = val; + + modes_changed = true; + + } else { + return -EINVAL; + } + + if (modes_changed) { + drm_helper_probe_single_connector_modes(connector, 0, 0); + + if (crtc) + drm_crtc_helper_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, + crtc->primary->fb); + } + + return 0; +} + +static const struct drm_encoder_slave_funcs ch7006_encoder_funcs = { + .set_config = ch7006_encoder_set_config, + .destroy = ch7006_encoder_destroy, + .dpms = ch7006_encoder_dpms, + .save = ch7006_encoder_save, + .restore = ch7006_encoder_restore, + .mode_fixup = ch7006_encoder_mode_fixup, + .mode_valid = ch7006_encoder_mode_valid, + .mode_set = ch7006_encoder_mode_set, + .detect = ch7006_encoder_detect, + .get_modes = ch7006_encoder_get_modes, + .create_resources = ch7006_encoder_create_resources, + .set_property = ch7006_encoder_set_property, +}; + + +/* I2C driver functions */ + +static int ch7006_probe(struct i2c_client *client) +{ + uint8_t addr = CH7006_VERSION_ID; + uint8_t val; + int ret; + + ch7006_dbg(client, "\n"); + + ret = i2c_master_send(client, &addr, sizeof(addr)); + if (ret < 0) + goto fail; + + ret = i2c_master_recv(client, &val, sizeof(val)); + if (ret < 0) + goto fail; + + ch7006_info(client, "Detected version ID: %x\n", val); + + /* I don't know what this is for, but otherwise I get no + * signal. + */ + ch7006_write(client, 0x3d, 0x0); + + return 0; + +fail: + ch7006_err(client, "Error %d reading version ID\n", ret); + + return -ENODEV; +} + +static void ch7006_remove(struct i2c_client *client) +{ + ch7006_dbg(client, "\n"); +} + +static int ch7006_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + ch7006_dbg(client, "\n"); + + ch7006_write(client, 0x3d, 0x0); + + return 0; +} + +static int ch7006_encoder_init(struct i2c_client *client, + struct drm_device *dev, + struct drm_encoder_slave *encoder) +{ + struct ch7006_priv *priv; + int i; + + ch7006_dbg(client, "\n"); + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + encoder->slave_priv = priv; + encoder->slave_funcs = &ch7006_encoder_funcs; + + priv->norm = TV_NORM_PAL; + priv->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic; + priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + priv->scale = 1; + priv->contrast = 50; + priv->brightness = 50; + priv->flicker = 50; + priv->hmargin = 50; + priv->vmargin = 50; + priv->last_dpms = -1; + priv->chip_version = ch7006_read(client, CH7006_VERSION_ID); + + if (ch7006_tv_norm) { + for (i = 0; i < NUM_TV_NORMS; i++) { + if (!strcmp(ch7006_tv_norm_names[i], ch7006_tv_norm)) { + priv->norm = i; + break; + } + } + + if (i == NUM_TV_NORMS) + ch7006_err(client, "Invalid TV norm setting \"%s\".\n", + ch7006_tv_norm); + } + + if (ch7006_scale >= 0 && ch7006_scale <= 2) + priv->scale = ch7006_scale; + else + ch7006_err(client, "Invalid scale setting \"%d\".\n", + ch7006_scale); + + return 0; +} + +static const struct i2c_device_id ch7006_ids[] = { + { "ch7006" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ch7006_ids); + +static const struct dev_pm_ops ch7006_pm_ops = { + .resume = ch7006_resume, +}; + +static struct drm_i2c_encoder_driver ch7006_driver = { + .i2c_driver = { + .probe = ch7006_probe, + .remove = ch7006_remove, + + .driver = { + .name = "ch7006", + .pm = &ch7006_pm_ops, + }, + + .id_table = ch7006_ids, + }, + + .encoder_init = ch7006_encoder_init, +}; + + +/* Module initialization */ + +static int __init ch7006_init(void) +{ + return drm_i2c_encoder_register(THIS_MODULE, &ch7006_driver); +} + +static void __exit ch7006_exit(void) +{ + drm_i2c_encoder_unregister(&ch7006_driver); +} + +int ch7006_debug; +module_param_named(debug, ch7006_debug, int, 0600); +MODULE_PARM_DESC(debug, "Enable debug output."); + +char *ch7006_tv_norm; +module_param_named(tv_norm, ch7006_tv_norm, charp, 0600); +MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" + "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, PAL-60, NTSC-M, NTSC-J.\n" + "\t\tDefault: PAL"); + +int ch7006_scale = 1; +module_param_named(scale, ch7006_scale, int, 0600); +MODULE_PARM_DESC(scale, "Default scale.\n" + "\t\tSupported: 0 -> Select video modes with a higher blanking ratio.\n" + "\t\t\t1 -> Select default video modes.\n" + "\t\t\t2 -> Select video modes with a lower blanking ratio."); + +MODULE_AUTHOR("Francisco Jerez "); +MODULE_DESCRIPTION("Chrontel ch7006 TV encoder driver"); +MODULE_LICENSE("GPL and additional rights"); + +module_init(ch7006_init); +module_exit(ch7006_exit); diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c new file mode 100644 index 000000000000..6afe6d0ee630 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 "ch7006_priv.h" + +const char * const ch7006_tv_norm_names[] = { + [TV_NORM_PAL] = "PAL", + [TV_NORM_PAL_M] = "PAL-M", + [TV_NORM_PAL_N] = "PAL-N", + [TV_NORM_PAL_NC] = "PAL-Nc", + [TV_NORM_PAL_60] = "PAL-60", + [TV_NORM_NTSC_M] = "NTSC-M", + [TV_NORM_NTSC_J] = "NTSC-J", +}; + +#define NTSC_LIKE_TIMINGS .vrefresh = 60 * fixed1/1.001, \ + .vdisplay = 480, \ + .vtotal = 525, \ + .hvirtual = 660 + +#define PAL_LIKE_TIMINGS .vrefresh = 50 * fixed1, \ + .vdisplay = 576, \ + .vtotal = 625, \ + .hvirtual = 810 + +const struct ch7006_tv_norm_info ch7006_tv_norms[] = { + [TV_NORM_NTSC_M] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.339 * fixed1, + .subc_freq = 3579545 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC), + .voffset = 0, + }, + [TV_NORM_NTSC_J] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.286 * fixed1, + .subc_freq = 3579545 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC_J), + .voffset = 0, + }, + [TV_NORM_PAL] = { + PAL_LIKE_TIMINGS, + .black_level = 0.3 * fixed1, + .subc_freq = 4433618.75 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), + .voffset = 0, + }, + [TV_NORM_PAL_M] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.339 * fixed1, + .subc_freq = 3575611.433 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M), + .voffset = 16, + }, + + /* The following modes seem to work right but they're + * undocumented */ + + [TV_NORM_PAL_N] = { + PAL_LIKE_TIMINGS, + .black_level = 0.339 * fixed1, + .subc_freq = 4433618.75 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), + .voffset = 0, + }, + [TV_NORM_PAL_NC] = { + PAL_LIKE_TIMINGS, + .black_level = 0.3 * fixed1, + .subc_freq = 3582056.25 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL), + .voffset = 0, + }, + [TV_NORM_PAL_60] = { + NTSC_LIKE_TIMINGS, + .black_level = 0.3 * fixed1, + .subc_freq = 4433618.75 * fixed1, + .dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M), + .voffset = 16, + }, +}; + +#define __MODE(f, hd, vd, ht, vt, hsynp, vsynp, \ + subc, scale, scale_mask, norm_mask, e_hd, e_vd) { \ + .mode = { \ + .name = #hd "x" #vd, \ + .status = 0, \ + .type = DRM_MODE_TYPE_DRIVER, \ + .clock = f, \ + .hdisplay = hd, \ + .hsync_start = e_hd + 16, \ + .hsync_end = e_hd + 80, \ + .htotal = ht, \ + .hskew = 0, \ + .vdisplay = vd, \ + .vsync_start = vd + 10, \ + .vsync_end = vd + 26, \ + .vtotal = vt, \ + .vscan = 0, \ + .flags = DRM_MODE_FLAG_##hsynp##HSYNC | \ + DRM_MODE_FLAG_##vsynp##VSYNC, \ + }, \ + .enc_hdisp = e_hd, \ + .enc_vdisp = e_vd, \ + .subc_coeff = subc * fixed1, \ + .dispmode = bitfs(CH7006_DISPMODE_SCALING_RATIO, scale) | \ + bitfs(CH7006_DISPMODE_INPUT_RES, e_hd##x##e_vd), \ + .valid_scales = scale_mask, \ + .valid_norms = norm_mask \ + } + +#define MODE(f, hd, vd, ht, vt, hsynp, vsynp, \ + subc, scale, scale_mask, norm_mask) \ + __MODE(f, hd, vd, ht, vt, hsynp, vsynp, subc, scale, \ + scale_mask, norm_mask, hd, vd) + +#define NTSC_LIKE (1 << TV_NORM_NTSC_M | 1 << TV_NORM_NTSC_J | \ + 1 << TV_NORM_PAL_M | 1 << TV_NORM_PAL_60) + +#define PAL_LIKE (1 << TV_NORM_PAL | 1 << TV_NORM_PAL_N | 1 << TV_NORM_PAL_NC) + +const struct ch7006_mode ch7006_modes[] = { + MODE(21000, 512, 384, 840, 500, N, N, 181.797557582, 5_4, 0x6, PAL_LIKE), + MODE(26250, 512, 384, 840, 625, N, N, 145.438046066, 1_1, 0x1, PAL_LIKE), + MODE(20140, 512, 384, 800, 420, N, N, 213.257083791, 5_4, 0x4, NTSC_LIKE), + MODE(24671, 512, 384, 784, 525, N, N, 174.0874153, 1_1, 0x3, NTSC_LIKE), + MODE(28125, 720, 400, 1125, 500, N, N, 135.742176298, 5_4, 0x6, PAL_LIKE), + MODE(34875, 720, 400, 1116, 625, N, N, 109.469496898, 1_1, 0x1, PAL_LIKE), + MODE(23790, 720, 400, 945, 420, N, N, 160.475642016, 5_4, 0x4, NTSC_LIKE), + MODE(29455, 720, 400, 936, 525, N, N, 129.614941843, 1_1, 0x3, NTSC_LIKE), + MODE(25000, 640, 400, 1000, 500, N, N, 152.709948279, 5_4, 0x6, PAL_LIKE), + MODE(31500, 640, 400, 1008, 625, N, N, 121.198371646, 1_1, 0x1, PAL_LIKE), + MODE(21147, 640, 400, 840, 420, N, N, 180.535097338, 5_4, 0x4, NTSC_LIKE), + MODE(26434, 640, 400, 840, 525, N, N, 144.42807787, 1_1, 0x2, NTSC_LIKE), + MODE(30210, 640, 400, 840, 600, N, N, 126.374568276, 7_8, 0x1, NTSC_LIKE), + MODE(21000, 640, 480, 840, 500, N, N, 181.797557582, 5_4, 0x4, PAL_LIKE), + MODE(26250, 640, 480, 840, 625, N, N, 145.438046066, 1_1, 0x2, PAL_LIKE), + MODE(31500, 640, 480, 840, 750, N, N, 121.198371646, 5_6, 0x1, PAL_LIKE), + MODE(24671, 640, 480, 784, 525, N, N, 174.0874153, 1_1, 0x4, NTSC_LIKE), + MODE(28196, 640, 480, 784, 600, N, N, 152.326488422, 7_8, 0x2, NTSC_LIKE), + MODE(30210, 640, 480, 800, 630, N, N, 142.171389101, 5_6, 0x1, NTSC_LIKE), + __MODE(29500, 720, 576, 944, 625, P, P, 145.592111636, 1_1, 0x7, PAL_LIKE, 800, 600), + MODE(36000, 800, 600, 960, 750, P, P, 119.304647022, 5_6, 0x6, PAL_LIKE), + MODE(39000, 800, 600, 936, 836, P, P, 110.127366499, 3_4, 0x1, PAL_LIKE), + MODE(39273, 800, 600, 1040, 630, P, P, 145.816809399, 5_6, 0x4, NTSC_LIKE), + MODE(43636, 800, 600, 1040, 700, P, P, 131.235128487, 3_4, 0x2, NTSC_LIKE), + MODE(47832, 800, 600, 1064, 750, P, P, 119.723275165, 7_10, 0x1, NTSC_LIKE), + {} +}; + +const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, + const struct drm_display_mode *drm_mode) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + const struct ch7006_mode *mode; + + for (mode = ch7006_modes; mode->mode.clock; mode++) { + + if (~mode->valid_norms & 1<norm) + continue; + + if (mode->mode.hdisplay != drm_mode->hdisplay || + mode->mode.vdisplay != drm_mode->vdisplay || + mode->mode.vtotal != drm_mode->vtotal || + mode->mode.htotal != drm_mode->htotal || + mode->mode.clock != drm_mode->clock) + continue; + + return mode; + } + + return NULL; +} + +/* Some common HW state calculation code */ + +void ch7006_setup_levels(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + uint8_t *regs = priv->state.regs; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + int gain; + int black_level; + + /* Set DAC_GAIN if the voltage drop between white and black is + * high enough. */ + if (norm->black_level < 339*fixed1/1000) { + gain = 76; + + regs[CH7006_INPUT_FORMAT] |= CH7006_INPUT_FORMAT_DAC_GAIN; + } else { + gain = 71; + + regs[CH7006_INPUT_FORMAT] &= ~CH7006_INPUT_FORMAT_DAC_GAIN; + } + + black_level = round_fixed(norm->black_level*26625)/gain; + + /* Correct it with the specified brightness. */ + black_level = interpolate(90, black_level, 208, priv->brightness); + + regs[CH7006_BLACK_LEVEL] = bitf(CH7006_BLACK_LEVEL_0, black_level); + + ch7006_dbg(client, "black level: %d\n", black_level); +} + +void ch7006_setup_subcarrier(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_mode *mode = priv->mode; + uint32_t subc_inc; + + subc_inc = round_fixed((mode->subc_coeff >> 8) + * (norm->subc_freq >> 24)); + + setbitf(state, CH7006_SUBC_INC0, 28, subc_inc); + setbitf(state, CH7006_SUBC_INC1, 24, subc_inc); + setbitf(state, CH7006_SUBC_INC2, 20, subc_inc); + setbitf(state, CH7006_SUBC_INC3, 16, subc_inc); + setbitf(state, CH7006_SUBC_INC4, 12, subc_inc); + setbitf(state, CH7006_SUBC_INC5, 8, subc_inc); + setbitf(state, CH7006_SUBC_INC6, 4, subc_inc); + setbitf(state, CH7006_SUBC_INC7, 0, subc_inc); + + ch7006_dbg(client, "subcarrier inc: %u\n", subc_inc); +} + +void ch7006_setup_pll(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + uint8_t *regs = priv->state.regs; + const struct ch7006_mode *mode = priv->mode; + int n, best_n = 0; + int m, best_m = 0; + int freq, best_freq = 0; + + for (n = 0; n < CH7006_MAXN; n++) { + for (m = 0; m < CH7006_MAXM; m++) { + freq = CH7006_FREQ0*(n+2)/(m+2); + + if (abs(freq - mode->mode.clock) < + abs(best_freq - mode->mode.clock)) { + best_freq = freq; + best_n = n; + best_m = m; + } + } + } + + regs[CH7006_PLLOV] = bitf(CH7006_PLLOV_N_8, best_n) | + bitf(CH7006_PLLOV_M_8, best_m); + + regs[CH7006_PLLM] = bitf(CH7006_PLLM_0, best_m); + regs[CH7006_PLLN] = bitf(CH7006_PLLN_0, best_n); + + if (best_n < 108) + regs[CH7006_PLL_CONTROL] |= CH7006_PLL_CONTROL_CAPACITOR; + else + regs[CH7006_PLL_CONTROL] &= ~CH7006_PLL_CONTROL_CAPACITOR; + + ch7006_dbg(client, "n=%d m=%d f=%d c=%d\n", + best_n, best_m, best_freq, best_n < 108); +} + +void ch7006_setup_power_state(struct drm_encoder *encoder) +{ + struct ch7006_priv *priv = to_ch7006_priv(encoder); + uint8_t *power = &priv->state.regs[CH7006_POWER]; + int subconnector; + + subconnector = priv->select_subconnector ? priv->select_subconnector : + priv->subconnector; + + *power = CH7006_POWER_RESET; + + if (priv->last_dpms == DRM_MODE_DPMS_ON) { + switch (subconnector) { + case DRM_MODE_SUBCONNECTOR_SVIDEO: + *power |= bitfs(CH7006_POWER_LEVEL, CVBS_OFF); + break; + case DRM_MODE_SUBCONNECTOR_Composite: + *power |= bitfs(CH7006_POWER_LEVEL, SVIDEO_OFF); + break; + case DRM_MODE_SUBCONNECTOR_SCART: + *power |= bitfs(CH7006_POWER_LEVEL, NORMAL) | + CH7006_POWER_SCART; + break; + } + + } else { + if (priv->chip_version >= 0x20) + *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF); + else + *power |= bitfs(CH7006_POWER_LEVEL, POWER_OFF); + } +} + +void ch7006_setup_properties(struct drm_encoder *encoder) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct ch7006_priv *priv = to_ch7006_priv(encoder); + struct ch7006_state *state = &priv->state; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_mode *ch_mode = priv->mode; + const struct drm_display_mode *mode = &ch_mode->mode; + uint8_t *regs = state->regs; + int flicker, contrast, hpos, vpos; + uint64_t scale, aspect; + + flicker = interpolate(0, 2, 3, priv->flicker); + regs[CH7006_FFILTER] = bitf(CH7006_FFILTER_TEXT, flicker) | + bitf(CH7006_FFILTER_LUMA, flicker) | + bitf(CH7006_FFILTER_CHROMA, 1); + + contrast = interpolate(0, 5, 7, priv->contrast); + regs[CH7006_CONTRAST] = bitf(CH7006_CONTRAST_0, contrast); + + scale = norm->vtotal*fixed1; + do_div(scale, mode->vtotal); + + aspect = ch_mode->enc_hdisp*fixed1; + do_div(aspect, ch_mode->enc_vdisp); + + hpos = round_fixed((norm->hvirtual * aspect - mode->hdisplay * scale) + * priv->hmargin * mode->vtotal) / norm->vtotal / 100 / 4; + + setbitf(state, CH7006_POV, HPOS_8, hpos); + setbitf(state, CH7006_HPOS, 0, hpos); + + vpos = max(0, norm->vdisplay - round_fixed(mode->vdisplay*scale) + + norm->voffset) * priv->vmargin / 100 / 2; + + setbitf(state, CH7006_POV, VPOS_8, vpos); + setbitf(state, CH7006_VPOS, 0, vpos); + + ch7006_dbg(client, "hpos: %d, vpos: %d\n", hpos, vpos); +} + +/* HW access functions */ + +void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val) +{ + uint8_t buf[] = {addr, val}; + int ret; + + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); + if (ret < 0) + ch7006_err(client, "Error %d writing to subaddress 0x%x\n", + ret, addr); +} + +uint8_t ch7006_read(struct i2c_client *client, uint8_t addr) +{ + uint8_t val; + int ret; + + ret = i2c_master_send(client, &addr, sizeof(addr)); + if (ret < 0) + goto fail; + + ret = i2c_master_recv(client, &val, sizeof(val)); + if (ret < 0) + goto fail; + + return val; + +fail: + ch7006_err(client, "Error %d reading from subaddress 0x%x\n", + ret, addr); + return 0; +} + +void ch7006_state_load(struct i2c_client *client, + struct ch7006_state *state) +{ + ch7006_load_reg(client, state, CH7006_POWER); + + ch7006_load_reg(client, state, CH7006_DISPMODE); + ch7006_load_reg(client, state, CH7006_FFILTER); + ch7006_load_reg(client, state, CH7006_BWIDTH); + ch7006_load_reg(client, state, CH7006_INPUT_FORMAT); + ch7006_load_reg(client, state, CH7006_CLKMODE); + ch7006_load_reg(client, state, CH7006_START_ACTIVE); + ch7006_load_reg(client, state, CH7006_POV); + ch7006_load_reg(client, state, CH7006_BLACK_LEVEL); + ch7006_load_reg(client, state, CH7006_HPOS); + ch7006_load_reg(client, state, CH7006_VPOS); + ch7006_load_reg(client, state, CH7006_INPUT_SYNC); + ch7006_load_reg(client, state, CH7006_DETECT); + ch7006_load_reg(client, state, CH7006_CONTRAST); + ch7006_load_reg(client, state, CH7006_PLLOV); + ch7006_load_reg(client, state, CH7006_PLLM); + ch7006_load_reg(client, state, CH7006_PLLN); + ch7006_load_reg(client, state, CH7006_BCLKOUT); + ch7006_load_reg(client, state, CH7006_SUBC_INC0); + ch7006_load_reg(client, state, CH7006_SUBC_INC1); + ch7006_load_reg(client, state, CH7006_SUBC_INC2); + ch7006_load_reg(client, state, CH7006_SUBC_INC3); + ch7006_load_reg(client, state, CH7006_SUBC_INC4); + ch7006_load_reg(client, state, CH7006_SUBC_INC5); + ch7006_load_reg(client, state, CH7006_SUBC_INC6); + ch7006_load_reg(client, state, CH7006_SUBC_INC7); + ch7006_load_reg(client, state, CH7006_PLL_CONTROL); + ch7006_load_reg(client, state, CH7006_CALC_SUBC_INC0); +} + +void ch7006_state_save(struct i2c_client *client, + struct ch7006_state *state) +{ + ch7006_save_reg(client, state, CH7006_POWER); + + ch7006_save_reg(client, state, CH7006_DISPMODE); + ch7006_save_reg(client, state, CH7006_FFILTER); + ch7006_save_reg(client, state, CH7006_BWIDTH); + ch7006_save_reg(client, state, CH7006_INPUT_FORMAT); + ch7006_save_reg(client, state, CH7006_CLKMODE); + ch7006_save_reg(client, state, CH7006_START_ACTIVE); + ch7006_save_reg(client, state, CH7006_POV); + ch7006_save_reg(client, state, CH7006_BLACK_LEVEL); + ch7006_save_reg(client, state, CH7006_HPOS); + ch7006_save_reg(client, state, CH7006_VPOS); + ch7006_save_reg(client, state, CH7006_INPUT_SYNC); + ch7006_save_reg(client, state, CH7006_DETECT); + ch7006_save_reg(client, state, CH7006_CONTRAST); + ch7006_save_reg(client, state, CH7006_PLLOV); + ch7006_save_reg(client, state, CH7006_PLLM); + ch7006_save_reg(client, state, CH7006_PLLN); + ch7006_save_reg(client, state, CH7006_BCLKOUT); + ch7006_save_reg(client, state, CH7006_SUBC_INC0); + ch7006_save_reg(client, state, CH7006_SUBC_INC1); + ch7006_save_reg(client, state, CH7006_SUBC_INC2); + ch7006_save_reg(client, state, CH7006_SUBC_INC3); + ch7006_save_reg(client, state, CH7006_SUBC_INC4); + ch7006_save_reg(client, state, CH7006_SUBC_INC5); + ch7006_save_reg(client, state, CH7006_SUBC_INC6); + ch7006_save_reg(client, state, CH7006_SUBC_INC7); + ch7006_save_reg(client, state, CH7006_PLL_CONTROL); + ch7006_save_reg(client, state, CH7006_CALC_SUBC_INC0); + + state->regs[CH7006_FFILTER] = (state->regs[CH7006_FFILTER] & 0xf0) | + (state->regs[CH7006_FFILTER] & 0x0c) >> 2 | + (state->regs[CH7006_FFILTER] & 0x03) << 2; +} diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h new file mode 100644 index 000000000000..d7a91e17510f --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 __NOUVEAU_I2C_CH7006_PRIV_H__ +#define __NOUVEAU_I2C_CH7006_PRIV_H__ + +#include +#include + +#include + +typedef int64_t fixed; +#define fixed1 (1LL << 32) + +enum ch7006_tv_norm { + TV_NORM_PAL, + TV_NORM_PAL_M, + TV_NORM_PAL_N, + TV_NORM_PAL_NC, + TV_NORM_PAL_60, + TV_NORM_NTSC_M, + TV_NORM_NTSC_J, + NUM_TV_NORMS +}; + +struct ch7006_tv_norm_info { + fixed vrefresh; + int vdisplay; + int vtotal; + int hvirtual; + + fixed subc_freq; + fixed black_level; + + uint32_t dispmode; + int voffset; +}; + +struct ch7006_mode { + struct drm_display_mode mode; + + int enc_hdisp; + int enc_vdisp; + + fixed subc_coeff; + uint32_t dispmode; + + uint32_t valid_scales; + uint32_t valid_norms; +}; + +struct ch7006_state { + uint8_t regs[0x26]; +}; + +struct ch7006_priv { + struct ch7006_encoder_params params; + const struct ch7006_mode *mode; + + struct ch7006_state state; + struct ch7006_state saved_state; + + struct drm_property *scale_property; + + int select_subconnector; + int subconnector; + int hmargin; + int vmargin; + enum ch7006_tv_norm norm; + int brightness; + int contrast; + int flicker; + int scale; + + int chip_version; + int last_dpms; +}; + +#define to_ch7006_priv(x) \ + ((struct ch7006_priv *)to_encoder_slave(x)->slave_priv) + +extern int ch7006_debug; +extern char *ch7006_tv_norm; +extern int ch7006_scale; + +extern const char * const ch7006_tv_norm_names[]; +extern const struct ch7006_tv_norm_info ch7006_tv_norms[]; +extern const struct ch7006_mode ch7006_modes[]; + +const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, + const struct drm_display_mode *drm_mode); + +void ch7006_setup_levels(struct drm_encoder *encoder); +void ch7006_setup_subcarrier(struct drm_encoder *encoder); +void ch7006_setup_pll(struct drm_encoder *encoder); +void ch7006_setup_power_state(struct drm_encoder *encoder); +void ch7006_setup_properties(struct drm_encoder *encoder); + +void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val); +uint8_t ch7006_read(struct i2c_client *client, uint8_t addr); + +void ch7006_state_load(struct i2c_client *client, + struct ch7006_state *state); +void ch7006_state_save(struct i2c_client *client, + struct ch7006_state *state); + +/* Some helper macros */ + +#define ch7006_dbg(client, format, ...) do { \ + if (ch7006_debug) \ + dev_printk(KERN_DEBUG, &client->dev, \ + "%s: " format, __func__, ## __VA_ARGS__); \ + } while (0) +#define ch7006_info(client, format, ...) \ + dev_info(&client->dev, format, __VA_ARGS__) +#define ch7006_err(client, format, ...) \ + dev_err(&client->dev, format, __VA_ARGS__) + +#define __mask(src, bitfield) \ + (((2 << (1 ? bitfield)) - 1) & ~((1 << (0 ? bitfield)) - 1)) +#define mask(bitfield) __mask(bitfield) + +#define __bitf(src, bitfield, x) \ + (((x) >> (src) << (0 ? bitfield)) & __mask(src, bitfield)) +#define bitf(bitfield, x) __bitf(bitfield, x) +#define bitfs(bitfield, s) __bitf(bitfield, bitfield##_##s) +#define setbitf(state, reg, bitfield, x) \ + state->regs[reg] = (state->regs[reg] & ~mask(reg##_##bitfield)) \ + | bitf(reg##_##bitfield, x) + +#define __unbitf(src, bitfield, x) \ + ((x & __mask(src, bitfield)) >> (0 ? bitfield) << (src)) +#define unbitf(bitfield, x) __unbitf(bitfield, x) + +static inline int interpolate(int y0, int y1, int y2, int x) +{ + return y1 + (x < 50 ? y1 - y0 : y2 - y1) * (x - 50) / 50; +} + +static inline int32_t round_fixed(fixed x) +{ + return (x + fixed1/2) >> 32; +} + +#define ch7006_load_reg(client, state, reg) ch7006_write(client, reg, state->regs[reg]) +#define ch7006_save_reg(client, state, reg) state->regs[reg] = ch7006_read(client, reg) + +/* Fixed hardware specs */ + +#define CH7006_FREQ0 14318 +#define CH7006_MAXN 650 +#define CH7006_MAXM 315 + +/* Register definitions */ + +#define CH7006_DISPMODE 0x00 +#define CH7006_DISPMODE_INPUT_RES 0, 7:5 +#define CH7006_DISPMODE_INPUT_RES_512x384 0x0 +#define CH7006_DISPMODE_INPUT_RES_720x400 0x1 +#define CH7006_DISPMODE_INPUT_RES_640x400 0x2 +#define CH7006_DISPMODE_INPUT_RES_640x480 0x3 +#define CH7006_DISPMODE_INPUT_RES_800x600 0x4 +#define CH7006_DISPMODE_INPUT_RES_NATIVE 0x5 +#define CH7006_DISPMODE_OUTPUT_STD 0, 4:3 +#define CH7006_DISPMODE_OUTPUT_STD_PAL 0x0 +#define CH7006_DISPMODE_OUTPUT_STD_NTSC 0x1 +#define CH7006_DISPMODE_OUTPUT_STD_PAL_M 0x2 +#define CH7006_DISPMODE_OUTPUT_STD_NTSC_J 0x3 +#define CH7006_DISPMODE_SCALING_RATIO 0, 2:0 +#define CH7006_DISPMODE_SCALING_RATIO_5_4 0x0 +#define CH7006_DISPMODE_SCALING_RATIO_1_1 0x1 +#define CH7006_DISPMODE_SCALING_RATIO_7_8 0x2 +#define CH7006_DISPMODE_SCALING_RATIO_5_6 0x3 +#define CH7006_DISPMODE_SCALING_RATIO_3_4 0x4 +#define CH7006_DISPMODE_SCALING_RATIO_7_10 0x5 + +#define CH7006_FFILTER 0x01 +#define CH7006_FFILTER_TEXT 0, 5:4 +#define CH7006_FFILTER_LUMA 0, 3:2 +#define CH7006_FFILTER_CHROMA 0, 1:0 +#define CH7006_FFILTER_CHROMA_NO_DCRAWL 0x3 + +#define CH7006_BWIDTH 0x03 +#define CH7006_BWIDTH_5L_FFILER (1 << 7) +#define CH7006_BWIDTH_CVBS_NO_CHROMA (1 << 6) +#define CH7006_BWIDTH_CHROMA 0, 5:4 +#define CH7006_BWIDTH_SVIDEO_YPEAK (1 << 3) +#define CH7006_BWIDTH_SVIDEO_LUMA 0, 2:1 +#define CH7006_BWIDTH_CVBS_LUMA 0, 0:0 + +#define CH7006_INPUT_FORMAT 0x04 +#define CH7006_INPUT_FORMAT_DAC_GAIN (1 << 6) +#define CH7006_INPUT_FORMAT_RGB_PASS_THROUGH (1 << 5) +#define CH7006_INPUT_FORMAT_FORMAT 0, 3:0 +#define CH7006_INPUT_FORMAT_FORMAT_RGB16 0x0 +#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m16 0x1 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m16 0x2 +#define CH7006_INPUT_FORMAT_FORMAT_RGB15 0x3 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12C 0x4 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12I 0x5 +#define CH7006_INPUT_FORMAT_FORMAT_RGB24m8 0x6 +#define CH7006_INPUT_FORMAT_FORMAT_RGB16m8 0x7 +#define CH7006_INPUT_FORMAT_FORMAT_RGB15m8 0x8 +#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m8 0x9 + +#define CH7006_CLKMODE 0x06 +#define CH7006_CLKMODE_SUBC_LOCK (1 << 7) +#define CH7006_CLKMODE_MASTER (1 << 6) +#define CH7006_CLKMODE_POS_EDGE (1 << 4) +#define CH7006_CLKMODE_XCM 0, 3:2 +#define CH7006_CLKMODE_PCM 0, 1:0 + +#define CH7006_START_ACTIVE 0x07 +#define CH7006_START_ACTIVE_0 0, 7:0 + +#define CH7006_POV 0x08 +#define CH7006_POV_START_ACTIVE_8 8, 2:2 +#define CH7006_POV_HPOS_8 8, 1:1 +#define CH7006_POV_VPOS_8 8, 0:0 + +#define CH7006_BLACK_LEVEL 0x09 +#define CH7006_BLACK_LEVEL_0 0, 7:0 + +#define CH7006_HPOS 0x0a +#define CH7006_HPOS_0 0, 7:0 + +#define CH7006_VPOS 0x0b +#define CH7006_VPOS_0 0, 7:0 + +#define CH7006_INPUT_SYNC 0x0d +#define CH7006_INPUT_SYNC_EMBEDDED (1 << 3) +#define CH7006_INPUT_SYNC_OUTPUT (1 << 2) +#define CH7006_INPUT_SYNC_PVSYNC (1 << 1) +#define CH7006_INPUT_SYNC_PHSYNC (1 << 0) + +#define CH7006_POWER 0x0e +#define CH7006_POWER_SCART (1 << 4) +#define CH7006_POWER_RESET (1 << 3) +#define CH7006_POWER_LEVEL 0, 2:0 +#define CH7006_POWER_LEVEL_CVBS_OFF 0x0 +#define CH7006_POWER_LEVEL_POWER_OFF 0x1 +#define CH7006_POWER_LEVEL_SVIDEO_OFF 0x2 +#define CH7006_POWER_LEVEL_NORMAL 0x3 +#define CH7006_POWER_LEVEL_FULL_POWER_OFF 0x4 + +#define CH7006_DETECT 0x10 +#define CH7006_DETECT_SVIDEO_Y_TEST (1 << 3) +#define CH7006_DETECT_SVIDEO_C_TEST (1 << 2) +#define CH7006_DETECT_CVBS_TEST (1 << 1) +#define CH7006_DETECT_SENSE (1 << 0) + +#define CH7006_CONTRAST 0x11 +#define CH7006_CONTRAST_0 0, 2:0 + +#define CH7006_PLLOV 0x13 +#define CH7006_PLLOV_N_8 8, 2:1 +#define CH7006_PLLOV_M_8 8, 0:0 + +#define CH7006_PLLM 0x14 +#define CH7006_PLLM_0 0, 7:0 + +#define CH7006_PLLN 0x15 +#define CH7006_PLLN_0 0, 7:0 + +#define CH7006_BCLKOUT 0x17 + +#define CH7006_SUBC_INC0 0x18 +#define CH7006_SUBC_INC0_28 28, 3:0 + +#define CH7006_SUBC_INC1 0x19 +#define CH7006_SUBC_INC1_24 24, 3:0 + +#define CH7006_SUBC_INC2 0x1a +#define CH7006_SUBC_INC2_20 20, 3:0 + +#define CH7006_SUBC_INC3 0x1b +#define CH7006_SUBC_INC3_GPIO1_VAL (1 << 7) +#define CH7006_SUBC_INC3_GPIO0_VAL (1 << 6) +#define CH7006_SUBC_INC3_POUT_3_3V (1 << 5) +#define CH7006_SUBC_INC3_POUT_INV (1 << 4) +#define CH7006_SUBC_INC3_16 16, 3:0 + +#define CH7006_SUBC_INC4 0x1c +#define CH7006_SUBC_INC4_GPIO1_IN (1 << 7) +#define CH7006_SUBC_INC4_GPIO0_IN (1 << 6) +#define CH7006_SUBC_INC4_DS_INPUT (1 << 4) +#define CH7006_SUBC_INC4_12 12, 3:0 + +#define CH7006_SUBC_INC5 0x1d +#define CH7006_SUBC_INC5_8 8, 3:0 + +#define CH7006_SUBC_INC6 0x1e +#define CH7006_SUBC_INC6_4 4, 3:0 + +#define CH7006_SUBC_INC7 0x1f +#define CH7006_SUBC_INC7_0 0, 3:0 + +#define CH7006_PLL_CONTROL 0x20 +#define CH7006_PLL_CONTROL_CPI (1 << 5) +#define CH7006_PLL_CONTROL_CAPACITOR (1 << 4) +#define CH7006_PLL_CONTROL_7STAGES (1 << 3) +#define CH7006_PLL_CONTROL_DIGITAL_5V (1 << 2) +#define CH7006_PLL_CONTROL_ANALOG_5V (1 << 1) +#define CH7006_PLL_CONTROL_MEMORY_5V (1 << 0) + +#define CH7006_CALC_SUBC_INC0 0x21 +#define CH7006_CALC_SUBC_INC0_24 24, 4:3 +#define CH7006_CALC_SUBC_INC0_HYST 0, 2:1 +#define CH7006_CALC_SUBC_INC0_AUTO (1 << 0) + +#define CH7006_CALC_SUBC_INC1 0x22 +#define CH7006_CALC_SUBC_INC1_16 16, 7:0 + +#define CH7006_CALC_SUBC_INC2 0x23 +#define CH7006_CALC_SUBC_INC2_8 8, 7:0 + +#define CH7006_CALC_SUBC_INC3 0x24 +#define CH7006_CALC_SUBC_INC3_0 0, 7:0 + +#define CH7006_VERSION_ID 0x25 + +#endif diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c new file mode 100644 index 000000000000..39b01c897518 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 + +#include +#include +#include +#include + +#include + +struct sil164_priv { + struct sil164_encoder_params config; + struct i2c_client *duallink_slave; + + uint8_t saved_state[0x10]; + uint8_t saved_slave_state[0x10]; +}; + +#define to_sil164_priv(x) \ + ((struct sil164_priv *)to_encoder_slave(x)->slave_priv) + +#define sil164_dbg(client, format, ...) do { \ + if (drm_debug_enabled(DRM_UT_KMS)) \ + dev_printk(KERN_DEBUG, &client->dev, \ + "%s: " format, __func__, ## __VA_ARGS__); \ + } while (0) +#define sil164_info(client, format, ...) \ + dev_info(&client->dev, format, __VA_ARGS__) +#define sil164_err(client, format, ...) \ + dev_err(&client->dev, format, __VA_ARGS__) + +#define SIL164_I2C_ADDR_MASTER 0x38 +#define SIL164_I2C_ADDR_SLAVE 0x39 + +/* HW register definitions */ + +#define SIL164_VENDOR_LO 0x0 +#define SIL164_VENDOR_HI 0x1 +#define SIL164_DEVICE_LO 0x2 +#define SIL164_DEVICE_HI 0x3 +#define SIL164_REVISION 0x4 +#define SIL164_FREQ_MIN 0x6 +#define SIL164_FREQ_MAX 0x7 +#define SIL164_CONTROL0 0x8 +# define SIL164_CONTROL0_POWER_ON 0x01 +# define SIL164_CONTROL0_EDGE_RISING 0x02 +# define SIL164_CONTROL0_INPUT_24BIT 0x04 +# define SIL164_CONTROL0_DUAL_EDGE 0x08 +# define SIL164_CONTROL0_HSYNC_ON 0x10 +# define SIL164_CONTROL0_VSYNC_ON 0x20 +#define SIL164_DETECT 0x9 +# define SIL164_DETECT_INTR_STAT 0x01 +# define SIL164_DETECT_HOTPLUG_STAT 0x02 +# define SIL164_DETECT_RECEIVER_STAT 0x04 +# define SIL164_DETECT_INTR_MODE_RECEIVER 0x00 +# define SIL164_DETECT_INTR_MODE_HOTPLUG 0x08 +# define SIL164_DETECT_OUT_MODE_HIGH 0x00 +# define SIL164_DETECT_OUT_MODE_INTR 0x10 +# define SIL164_DETECT_OUT_MODE_RECEIVER 0x20 +# define SIL164_DETECT_OUT_MODE_HOTPLUG 0x30 +# define SIL164_DETECT_VSWING_STAT 0x80 +#define SIL164_CONTROL1 0xa +# define SIL164_CONTROL1_DESKEW_ENABLE 0x10 +# define SIL164_CONTROL1_DESKEW_INCR_SHIFT 5 +#define SIL164_GPIO 0xb +#define SIL164_CONTROL2 0xc +# define SIL164_CONTROL2_FILTER_ENABLE 0x01 +# define SIL164_CONTROL2_FILTER_SETTING_SHIFT 1 +# define SIL164_CONTROL2_DUALLINK_MASTER 0x40 +# define SIL164_CONTROL2_SYNC_CONT 0x80 +#define SIL164_DUALLINK 0xd +# define SIL164_DUALLINK_ENABLE 0x10 +# define SIL164_DUALLINK_SKEW_SHIFT 5 +#define SIL164_PLLZONE 0xe +# define SIL164_PLLZONE_STAT 0x08 +# define SIL164_PLLZONE_FORCE_ON 0x10 +# define SIL164_PLLZONE_FORCE_HIGH 0x20 + +/* HW access functions */ + +static void +sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val) +{ + uint8_t buf[] = {addr, val}; + int ret; + + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); + if (ret < 0) + sil164_err(client, "Error %d writing to subaddress 0x%x\n", + ret, addr); +} + +static uint8_t +sil164_read(struct i2c_client *client, uint8_t addr) +{ + uint8_t val; + int ret; + + ret = i2c_master_send(client, &addr, sizeof(addr)); + if (ret < 0) + goto fail; + + ret = i2c_master_recv(client, &val, sizeof(val)); + if (ret < 0) + goto fail; + + return val; + +fail: + sil164_err(client, "Error %d reading from subaddress 0x%x\n", + ret, addr); + return 0; +} + +static void +sil164_save_state(struct i2c_client *client, uint8_t *state) +{ + int i; + + for (i = 0x8; i <= 0xe; i++) + state[i] = sil164_read(client, i); +} + +static void +sil164_restore_state(struct i2c_client *client, uint8_t *state) +{ + int i; + + for (i = 0x8; i <= 0xe; i++) + sil164_write(client, i, state[i]); +} + +static void +sil164_set_power_state(struct i2c_client *client, bool on) +{ + uint8_t control0 = sil164_read(client, SIL164_CONTROL0); + + if (on) + control0 |= SIL164_CONTROL0_POWER_ON; + else + control0 &= ~SIL164_CONTROL0_POWER_ON; + + sil164_write(client, SIL164_CONTROL0, control0); +} + +static void +sil164_init_state(struct i2c_client *client, + struct sil164_encoder_params *config, + bool duallink) +{ + sil164_write(client, SIL164_CONTROL0, + SIL164_CONTROL0_HSYNC_ON | + SIL164_CONTROL0_VSYNC_ON | + (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) | + (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) | + (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0)); + + sil164_write(client, SIL164_DETECT, + SIL164_DETECT_INTR_STAT | + SIL164_DETECT_OUT_MODE_RECEIVER); + + sil164_write(client, SIL164_CONTROL1, + (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) | + (((config->input_skew + 4) & 0x7) + << SIL164_CONTROL1_DESKEW_INCR_SHIFT)); + + sil164_write(client, SIL164_CONTROL2, + SIL164_CONTROL2_SYNC_CONT | + (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) | + (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT)); + + sil164_write(client, SIL164_PLLZONE, 0); + + if (duallink) + sil164_write(client, SIL164_DUALLINK, + SIL164_DUALLINK_ENABLE | + (((config->duallink_skew + 4) & 0x7) + << SIL164_DUALLINK_SKEW_SHIFT)); + else + sil164_write(client, SIL164_DUALLINK, 0); +} + +/* DRM encoder functions */ + +static void +sil164_encoder_set_config(struct drm_encoder *encoder, void *params) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + priv->config = *(struct sil164_encoder_params *)params; +} + +static void +sil164_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + bool on = (mode == DRM_MODE_DPMS_ON); + bool duallink = (on && encoder->crtc->mode.clock > 165000); + + sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on); + + if (priv->duallink_slave) + sil164_set_power_state(priv->duallink_slave, duallink); +} + +static void +sil164_encoder_save(struct drm_encoder *encoder) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + sil164_save_state(drm_i2c_encoder_get_client(encoder), + priv->saved_state); + + if (priv->duallink_slave) + sil164_save_state(priv->duallink_slave, + priv->saved_slave_state); +} + +static void +sil164_encoder_restore(struct drm_encoder *encoder) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + sil164_restore_state(drm_i2c_encoder_get_client(encoder), + priv->saved_state); + + if (priv->duallink_slave) + sil164_restore_state(priv->duallink_slave, + priv->saved_slave_state); +} + +static int +sil164_encoder_mode_valid(struct drm_encoder *encoder, + const struct drm_display_mode *mode) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + if (mode->clock < 32000) + return MODE_CLOCK_LOW; + + if (mode->clock > 330000 || + (mode->clock > 165000 && !priv->duallink_slave)) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static void +sil164_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + bool duallink = adjusted_mode->clock > 165000; + + sil164_init_state(drm_i2c_encoder_get_client(encoder), + &priv->config, duallink); + + if (priv->duallink_slave) + sil164_init_state(priv->duallink_slave, + &priv->config, duallink); + + sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static enum drm_connector_status +sil164_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + + if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT) + return connector_status_connected; + else + return connector_status_disconnected; +} + +static int +sil164_encoder_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + return 0; +} + +static int +sil164_encoder_create_resources(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + return 0; +} + +static int +sil164_encoder_set_property(struct drm_encoder *encoder, + struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + return 0; +} + +static void +sil164_encoder_destroy(struct drm_encoder *encoder) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + i2c_unregister_device(priv->duallink_slave); + + kfree(priv); + drm_i2c_encoder_destroy(encoder); +} + +static const struct drm_encoder_slave_funcs sil164_encoder_funcs = { + .set_config = sil164_encoder_set_config, + .destroy = sil164_encoder_destroy, + .dpms = sil164_encoder_dpms, + .save = sil164_encoder_save, + .restore = sil164_encoder_restore, + .mode_valid = sil164_encoder_mode_valid, + .mode_set = sil164_encoder_mode_set, + .detect = sil164_encoder_detect, + .get_modes = sil164_encoder_get_modes, + .create_resources = sil164_encoder_create_resources, + .set_property = sil164_encoder_set_property, +}; + +/* I2C driver functions */ + +static int +sil164_probe(struct i2c_client *client) +{ + int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 | + sil164_read(client, SIL164_VENDOR_LO); + int device = sil164_read(client, SIL164_DEVICE_HI) << 8 | + sil164_read(client, SIL164_DEVICE_LO); + int rev = sil164_read(client, SIL164_REVISION); + + if (vendor != 0x1 || device != 0x6) { + sil164_dbg(client, "Unknown device %x:%x.%x\n", + vendor, device, rev); + return -ENODEV; + } + + sil164_info(client, "Detected device %x:%x.%x\n", + vendor, device, rev); + + return 0; +} + +static struct i2c_client * +sil164_detect_slave(struct i2c_client *client) +{ + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg = { + .addr = SIL164_I2C_ADDR_SLAVE, + .len = 0, + }; + const struct i2c_board_info info = { + I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE) + }; + + if (i2c_transfer(adap, &msg, 1) != 1) { + sil164_dbg(adap, "No dual-link slave found."); + return NULL; + } + + return i2c_new_client_device(adap, &info); +} + +static int +sil164_encoder_init(struct i2c_client *client, + struct drm_device *dev, + struct drm_encoder_slave *encoder) +{ + struct sil164_priv *priv; + struct i2c_client *slave_client; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + encoder->slave_priv = priv; + encoder->slave_funcs = &sil164_encoder_funcs; + + slave_client = sil164_detect_slave(client); + if (!IS_ERR(slave_client)) + priv->duallink_slave = slave_client; + + return 0; +} + +static const struct i2c_device_id sil164_ids[] = { + { "sil164" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, sil164_ids); + +static struct drm_i2c_encoder_driver sil164_driver = { + .i2c_driver = { + .probe = sil164_probe, + .driver = { + .name = "sil164", + }, + .id_table = sil164_ids, + }, + .encoder_init = sil164_encoder_init, +}; + +/* Module initialization */ + +static int __init +sil164_init(void) +{ + return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver); +} + +static void __exit +sil164_exit(void) +{ + drm_i2c_encoder_unregister(&sil164_driver); +} + +MODULE_AUTHOR("Francisco Jerez "); +MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver"); +MODULE_LICENSE("GPL and additional rights"); + +module_init(sil164_init); +module_exit(sil164_exit); diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index d3014027a812..4ffd8af6bf8b 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -32,7 +32,7 @@ #include "hw.h" #include -#include +#include static struct nvkm_i2c_bus_probe nv04_tv_encoder_info[] = { { diff --git a/drivers/gpu/drm/nouveau/include/dispnv04/i2c/ch7006.h b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/ch7006.h new file mode 100644 index 000000000000..1a6fa405f85b --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/ch7006.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 __NOUVEAU_I2C_CH7006_H__ +#define __NOUVEAU_I2C_CH7006_H__ + +/** + * struct ch7006_encoder_params + * + * Describes how the ch7006 is wired up with the GPU. It should be + * used as the @params parameter of its @set_config method. + * + * See "http://www.chrontel.com/pdf/7006.pdf" for their precise + * meaning. + */ +struct ch7006_encoder_params { + /* private: FIXME: document the members */ + enum { + CH7006_FORMAT_RGB16 = 0, + CH7006_FORMAT_YCrCb24m16, + CH7006_FORMAT_RGB24m16, + CH7006_FORMAT_RGB15, + CH7006_FORMAT_RGB24m12C, + CH7006_FORMAT_RGB24m12I, + CH7006_FORMAT_RGB24m8, + CH7006_FORMAT_RGB16m8, + CH7006_FORMAT_RGB15m8, + CH7006_FORMAT_YCrCb24m8, + } input_format; + + enum { + CH7006_CLOCK_SLAVE = 0, + CH7006_CLOCK_MASTER, + } clock_mode; + + enum { + CH7006_CLOCK_EDGE_NEG = 0, + CH7006_CLOCK_EDGE_POS, + } clock_edge; + + int xcm, pcm; + + enum { + CH7006_SYNC_SLAVE = 0, + CH7006_SYNC_MASTER, + } sync_direction; + + enum { + CH7006_SYNC_SEPARATED = 0, + CH7006_SYNC_EMBEDDED, + } sync_encoding; + + enum { + CH7006_POUT_1_8V = 0, + CH7006_POUT_3_3V, + } pout_level; + + enum { + CH7006_ACTIVE_HSYNC = 0, + CH7006_ACTIVE_DSTART, + } active_detect; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/include/dispnv04/i2c/sil164.h b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/sil164.h new file mode 100644 index 000000000000..b86750d7abe1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/sil164.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 __NOUVEAU_I2C_SIL164_H__ +#define __NOUVEAU_I2C_SIL164_H__ + +/** + * struct sil164_encoder_params + * + * Describes how the sil164 is connected to the GPU. It should be used + * as the @params parameter of its @set_config method. + * + * See "http://www.siliconimage.com/docs/SiI-DS-0021-E-164.pdf". + */ +struct sil164_encoder_params { + /* private: FIXME: document the members */ + enum { + SIL164_INPUT_EDGE_FALLING = 0, + SIL164_INPUT_EDGE_RISING + } input_edge; + + enum { + SIL164_INPUT_WIDTH_12BIT = 0, + SIL164_INPUT_WIDTH_24BIT + } input_width; + + enum { + SIL164_INPUT_SINGLE_EDGE = 0, + SIL164_INPUT_DUAL_EDGE + } input_dual; + + enum { + SIL164_PLL_FILTER_ON = 0, + SIL164_PLL_FILTER_OFF, + } pll_filter; + + int input_skew; /** < Allowed range [-4, 3], use 0 for no de-skew. */ + int duallink_skew; /** < Allowed range [-4, 3]. */ +}; + +#endif diff --git a/include/drm/i2c/ch7006.h b/include/drm/i2c/ch7006.h deleted file mode 100644 index 5305b9797f93..000000000000 --- a/include/drm/i2c/ch7006.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2009 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 __DRM_I2C_CH7006_H__ -#define __DRM_I2C_CH7006_H__ - -/** - * struct ch7006_encoder_params - * - * Describes how the ch7006 is wired up with the GPU. It should be - * used as the @params parameter of its @set_config method. - * - * See "http://www.chrontel.com/pdf/7006.pdf" for their precise - * meaning. - */ -struct ch7006_encoder_params { - /* private: FIXME: document the members */ - enum { - CH7006_FORMAT_RGB16 = 0, - CH7006_FORMAT_YCrCb24m16, - CH7006_FORMAT_RGB24m16, - CH7006_FORMAT_RGB15, - CH7006_FORMAT_RGB24m12C, - CH7006_FORMAT_RGB24m12I, - CH7006_FORMAT_RGB24m8, - CH7006_FORMAT_RGB16m8, - CH7006_FORMAT_RGB15m8, - CH7006_FORMAT_YCrCb24m8, - } input_format; - - enum { - CH7006_CLOCK_SLAVE = 0, - CH7006_CLOCK_MASTER, - } clock_mode; - - enum { - CH7006_CLOCK_EDGE_NEG = 0, - CH7006_CLOCK_EDGE_POS, - } clock_edge; - - int xcm, pcm; - - enum { - CH7006_SYNC_SLAVE = 0, - CH7006_SYNC_MASTER, - } sync_direction; - - enum { - CH7006_SYNC_SEPARATED = 0, - CH7006_SYNC_EMBEDDED, - } sync_encoding; - - enum { - CH7006_POUT_1_8V = 0, - CH7006_POUT_3_3V, - } pout_level; - - enum { - CH7006_ACTIVE_HSYNC = 0, - CH7006_ACTIVE_DSTART, - } active_detect; -}; - -#endif diff --git a/include/drm/i2c/sil164.h b/include/drm/i2c/sil164.h deleted file mode 100644 index ddf248693c8b..000000000000 --- a/include/drm/i2c/sil164.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 __DRM_I2C_SIL164_H__ -#define __DRM_I2C_SIL164_H__ - -/** - * struct sil164_encoder_params - * - * Describes how the sil164 is connected to the GPU. It should be used - * as the @params parameter of its @set_config method. - * - * See "http://www.siliconimage.com/docs/SiI-DS-0021-E-164.pdf". - */ -struct sil164_encoder_params { - /* private: FIXME: document the members */ - enum { - SIL164_INPUT_EDGE_FALLING = 0, - SIL164_INPUT_EDGE_RISING - } input_edge; - - enum { - SIL164_INPUT_WIDTH_12BIT = 0, - SIL164_INPUT_WIDTH_24BIT - } input_width; - - enum { - SIL164_INPUT_SINGLE_EDGE = 0, - SIL164_INPUT_DUAL_EDGE - } input_dual; - - enum { - SIL164_PLL_FILTER_ON = 0, - SIL164_PLL_FILTER_OFF, - } pll_filter; - - int input_skew; /** < Allowed range [-4, 3], use 0 for no de-skew. */ - int duallink_skew; /** < Allowed range [-4, 3]. */ -}; - -#endif -- cgit v1.2.3-59-g8ed1b From a73583107af9b42c0a28045e4e30ec3fab2dbcd1 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 6 Jan 2025 01:00:14 +0200 Subject: drm/nouveau: vendor in drm_encoder_slave API Nouveau driver is the only user of the drm_encoder_slave API. Rework necessary bits of drm_encoder_slave into the nouveau_i2c_encoder API and drop drm_encoder_slave.c from the DRM KMS helper. Suggested-by: Laurent Pinchart Signed-off-by: Dmitry Baryshkov Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250106-nouveau-encoder-slave-v3-2-1d37d2f2c67f@linaro.org --- drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/drm_encoder_slave.c | 182 ---------------- drivers/gpu/drm/nouveau/dispnv04/Kbuild | 1 + drivers/gpu/drm/nouveau/dispnv04/dfp.c | 15 +- drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c | 30 +-- drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c | 8 +- drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h | 4 +- drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c | 30 +-- .../gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c | 145 +++++++++++++ drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | 22 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 4 +- .../drm/nouveau/include/dispnv04/i2c/encoder_i2c.h | 220 +++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_connector.c | 10 +- drivers/gpu/drm/nouveau/nouveau_encoder.h | 13 +- include/drm/drm_encoder_slave.h | 241 --------------------- 15 files changed, 433 insertions(+), 493 deletions(-) delete mode 100644 drivers/gpu/drm/drm_encoder_slave.c create mode 100644 drivers/gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c create mode 100644 drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h delete mode 100644 include/drm/drm_encoder_slave.h (limited to 'drivers') diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 19fb370fbc56..85af94bb907d 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -135,7 +135,6 @@ drm_kms_helper-y := \ drm_atomic_state_helper.o \ drm_crtc_helper.o \ drm_damage_helper.o \ - drm_encoder_slave.o \ drm_flip_work.o \ drm_format_helper.o \ drm_gem_atomic_helper.o \ diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c deleted file mode 100644 index e464429d32df..000000000000 --- a/drivers/gpu/drm/drm_encoder_slave.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2009 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 - -#include - -/** - * drm_i2c_encoder_init - Initialize an I2C slave encoder - * @dev: DRM device. - * @encoder: Encoder to be attached to the I2C device. You aren't - * required to have called drm_encoder_init() before. - * @adap: I2C adapter that will be used to communicate with - * the device. - * @info: Information that will be used to create the I2C device. - * Required fields are @addr and @type. - * - * Create an I2C device on the specified bus (the module containing its - * driver is transparently loaded) and attach it to the specified - * &drm_encoder_slave. The @slave_funcs field will be initialized with - * the hooks provided by the slave driver. - * - * If @info.platform_data is non-NULL it will be used as the initial - * slave config. - * - * Returns 0 on success or a negative errno on failure, in particular, - * -ENODEV is returned when no matching driver is found. - */ -int drm_i2c_encoder_init(struct drm_device *dev, - struct drm_encoder_slave *encoder, - struct i2c_adapter *adap, - const struct i2c_board_info *info) -{ - struct module *module = NULL; - struct i2c_client *client; - struct drm_i2c_encoder_driver *encoder_drv; - int err = 0; - - request_module("%s%s", I2C_MODULE_PREFIX, info->type); - - client = i2c_new_client_device(adap, info); - if (!i2c_client_has_driver(client)) { - err = -ENODEV; - goto fail_unregister; - } - - module = client->dev.driver->owner; - if (!try_module_get(module)) { - err = -ENODEV; - goto fail_unregister; - } - - encoder->bus_priv = client; - - encoder_drv = to_drm_i2c_encoder_driver(to_i2c_driver(client->dev.driver)); - - err = encoder_drv->encoder_init(client, dev, encoder); - if (err) - goto fail_module_put; - - if (info->platform_data) - encoder->slave_funcs->set_config(&encoder->base, - info->platform_data); - - return 0; - -fail_module_put: - module_put(module); -fail_unregister: - i2c_unregister_device(client); - return err; -} -EXPORT_SYMBOL(drm_i2c_encoder_init); - -/** - * drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder - * @drm_encoder: Encoder to be unregistered. - * - * This should be called from the @destroy method of an I2C slave - * encoder driver once I2C access is no longer needed. - */ -void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder) -{ - struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder); - struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder); - struct module *module = client->dev.driver->owner; - - i2c_unregister_device(client); - encoder->bus_priv = NULL; - - module_put(module); -} -EXPORT_SYMBOL(drm_i2c_encoder_destroy); - -/* - * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs: - */ - -static inline const struct drm_encoder_slave_funcs * -get_slave_funcs(struct drm_encoder *enc) -{ - return to_encoder_slave(enc)->slave_funcs; -} - -void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - get_slave_funcs(encoder)->dpms(encoder, mode); -} -EXPORT_SYMBOL(drm_i2c_encoder_dpms); - -bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - if (!get_slave_funcs(encoder)->mode_fixup) - return true; - - return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode); -} -EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup); - -void drm_i2c_encoder_prepare(struct drm_encoder *encoder) -{ - drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); -} -EXPORT_SYMBOL(drm_i2c_encoder_prepare); - -void drm_i2c_encoder_commit(struct drm_encoder *encoder) -{ - drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON); -} -EXPORT_SYMBOL(drm_i2c_encoder_commit); - -void drm_i2c_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); -} -EXPORT_SYMBOL(drm_i2c_encoder_mode_set); - -enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - return get_slave_funcs(encoder)->detect(encoder, connector); -} -EXPORT_SYMBOL(drm_i2c_encoder_detect); - -void drm_i2c_encoder_save(struct drm_encoder *encoder) -{ - get_slave_funcs(encoder)->save(encoder); -} -EXPORT_SYMBOL(drm_i2c_encoder_save); - -void drm_i2c_encoder_restore(struct drm_encoder *encoder) -{ - get_slave_funcs(encoder)->restore(encoder); -} -EXPORT_SYMBOL(drm_i2c_encoder_restore); diff --git a/drivers/gpu/drm/nouveau/dispnv04/Kbuild b/drivers/gpu/drm/nouveau/dispnv04/Kbuild index 949802882ebd..4c7bc6bb81b3 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/Kbuild +++ b/drivers/gpu/drm/nouveau/dispnv04/Kbuild @@ -6,6 +6,7 @@ nouveau-y += dispnv04/dac.o nouveau-y += dispnv04/dfp.o nouveau-y += dispnv04/disp.o nouveau-y += dispnv04/hw.o +nouveau-y += dispnv04/nouveau_i2c_encoder.o nouveau-y += dispnv04/overlay.o nouveau-y += dispnv04/tvmodesnv17.o nouveau-y += dispnv04/tvnv04.o diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 25fa41edcb3c..c724bacc67f8 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -171,7 +171,7 @@ static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) list_for_each_entry(slave, &dev->mode_config.encoder_list, head) { struct dcb_output *slave_dcb = nouveau_encoder(slave)->dcb; - if (slave_dcb->type == DCB_OUTPUT_TMDS && get_slave_funcs(slave) && + if (slave_dcb->type == DCB_OUTPUT_TMDS && get_encoder_i2c_funcs(slave) && slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr) return slave; } @@ -473,8 +473,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) /* Init external transmitters */ slave_encoder = get_tmds_slave(encoder); if (slave_encoder) - get_slave_funcs(slave_encoder)->mode_set( - slave_encoder, &nv_encoder->mode, &nv_encoder->mode); + get_encoder_i2c_funcs(slave_encoder)->mode_set(slave_encoder, + &nv_encoder->mode, + &nv_encoder->mode); helper->dpms(encoder, DRM_MODE_DPMS_ON); @@ -614,8 +615,8 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - if (get_slave_funcs(encoder)) - get_slave_funcs(encoder)->destroy(encoder); + if (get_encoder_i2c_funcs(encoder)) + get_encoder_i2c_funcs(encoder)->destroy(encoder); drm_encoder_cleanup(encoder); kfree(nv_encoder); @@ -649,8 +650,8 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) if (type < 0) return; - drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - &bus->i2c, &info[type].dev); + nouveau_i2c_encoder_init(dev, to_encoder_i2c(encoder), + &bus->i2c, &info[type].dev); } static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c index db4f95020fae..fd2150e07e36 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c @@ -47,14 +47,14 @@ static void ch7006_encoder_destroy(struct drm_encoder *encoder) drm_property_destroy(encoder->dev, priv->scale_property); kfree(priv); - to_encoder_slave(encoder)->slave_priv = NULL; + to_encoder_i2c(encoder)->encoder_i2c_priv = NULL; - drm_i2c_encoder_destroy(encoder); + nouveau_i2c_encoder_destroy(encoder); } static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_state *state = &priv->state; @@ -71,7 +71,7 @@ static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode) static void ch7006_encoder_save(struct drm_encoder *encoder) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); ch7006_dbg(client, "\n"); @@ -81,7 +81,7 @@ static void ch7006_encoder_save(struct drm_encoder *encoder) static void ch7006_encoder_restore(struct drm_encoder *encoder) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); ch7006_dbg(client, "\n"); @@ -116,7 +116,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *drm_mode, struct drm_display_mode *adjusted_mode) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_encoder_params *params = &priv->params; struct ch7006_state *state = &priv->state; @@ -179,7 +179,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder, static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encoder, struct drm_connector *connector) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_state *state = &priv->state; int det; @@ -285,7 +285,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder, struct drm_property *property, uint64_t val) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_state *state = &priv->state; struct drm_mode_config *conf = &encoder->dev->mode_config; @@ -370,7 +370,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder, return 0; } -static const struct drm_encoder_slave_funcs ch7006_encoder_funcs = { +static const struct nouveau_i2c_encoder_funcs ch7006_encoder_funcs = { .set_config = ch7006_encoder_set_config, .destroy = ch7006_encoder_destroy, .dpms = ch7006_encoder_dpms, @@ -437,7 +437,7 @@ static int ch7006_resume(struct device *dev) static int ch7006_encoder_init(struct i2c_client *client, struct drm_device *dev, - struct drm_encoder_slave *encoder) + struct nouveau_i2c_encoder *encoder) { struct ch7006_priv *priv; int i; @@ -448,8 +448,8 @@ static int ch7006_encoder_init(struct i2c_client *client, if (!priv) return -ENOMEM; - encoder->slave_priv = priv; - encoder->slave_funcs = &ch7006_encoder_funcs; + encoder->encoder_i2c_priv = priv; + encoder->encoder_i2c_funcs = &ch7006_encoder_funcs; priv->norm = TV_NORM_PAL; priv->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic; @@ -495,7 +495,7 @@ static const struct dev_pm_ops ch7006_pm_ops = { .resume = ch7006_resume, }; -static struct drm_i2c_encoder_driver ch7006_driver = { +static struct nouveau_i2c_encoder_driver ch7006_driver = { .i2c_driver = { .probe = ch7006_probe, .remove = ch7006_remove, @@ -516,12 +516,12 @@ static struct drm_i2c_encoder_driver ch7006_driver = { static int __init ch7006_init(void) { - return drm_i2c_encoder_register(THIS_MODULE, &ch7006_driver); + return i2c_add_driver(&ch7006_driver.i2c_driver); } static void __exit ch7006_exit(void) { - drm_i2c_encoder_unregister(&ch7006_driver); + i2c_del_driver(&ch7006_driver.i2c_driver); } int ch7006_debug; diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c index 6afe6d0ee630..e58d94451959 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c @@ -198,7 +198,7 @@ const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, void ch7006_setup_levels(struct drm_encoder *encoder) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); uint8_t *regs = priv->state.regs; const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; @@ -229,7 +229,7 @@ void ch7006_setup_levels(struct drm_encoder *encoder) void ch7006_setup_subcarrier(struct drm_encoder *encoder) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_state *state = &priv->state; const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; @@ -253,7 +253,7 @@ void ch7006_setup_subcarrier(struct drm_encoder *encoder) void ch7006_setup_pll(struct drm_encoder *encoder) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); uint8_t *regs = priv->state.regs; const struct ch7006_mode *mode = priv->mode; @@ -324,7 +324,7 @@ void ch7006_setup_power_state(struct drm_encoder *encoder) void ch7006_setup_properties(struct drm_encoder *encoder) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_state *state = &priv->state; const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h index d7a91e17510f..5ad5157a2c02 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h @@ -27,9 +27,9 @@ #ifndef __NOUVEAU_I2C_CH7006_PRIV_H__ #define __NOUVEAU_I2C_CH7006_PRIV_H__ -#include #include +#include #include typedef int64_t fixed; @@ -100,7 +100,7 @@ struct ch7006_priv { }; #define to_ch7006_priv(x) \ - ((struct ch7006_priv *)to_encoder_slave(x)->slave_priv) + ((struct ch7006_priv *)to_encoder_i2c(x)->encoder_i2c_priv) extern int ch7006_debug; extern char *ch7006_tv_norm; diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c index 39b01c897518..54ea8459332d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c +++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c @@ -27,10 +27,10 @@ #include #include -#include #include #include +#include #include struct sil164_priv { @@ -42,7 +42,7 @@ struct sil164_priv { }; #define to_sil164_priv(x) \ - ((struct sil164_priv *)to_encoder_slave(x)->slave_priv) + ((struct sil164_priv *)to_encoder_i2c(x)->encoder_i2c_priv) #define sil164_dbg(client, format, ...) do { \ if (drm_debug_enabled(DRM_UT_KMS)) \ @@ -222,7 +222,7 @@ sil164_encoder_dpms(struct drm_encoder *encoder, int mode) bool on = (mode == DRM_MODE_DPMS_ON); bool duallink = (on && encoder->crtc->mode.clock > 165000); - sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on); + sil164_set_power_state(nouveau_i2c_encoder_get_client(encoder), on); if (priv->duallink_slave) sil164_set_power_state(priv->duallink_slave, duallink); @@ -233,7 +233,7 @@ sil164_encoder_save(struct drm_encoder *encoder) { struct sil164_priv *priv = to_sil164_priv(encoder); - sil164_save_state(drm_i2c_encoder_get_client(encoder), + sil164_save_state(nouveau_i2c_encoder_get_client(encoder), priv->saved_state); if (priv->duallink_slave) @@ -246,7 +246,7 @@ sil164_encoder_restore(struct drm_encoder *encoder) { struct sil164_priv *priv = to_sil164_priv(encoder); - sil164_restore_state(drm_i2c_encoder_get_client(encoder), + sil164_restore_state(nouveau_i2c_encoder_get_client(encoder), priv->saved_state); if (priv->duallink_slave) @@ -278,7 +278,7 @@ sil164_encoder_mode_set(struct drm_encoder *encoder, struct sil164_priv *priv = to_sil164_priv(encoder); bool duallink = adjusted_mode->clock > 165000; - sil164_init_state(drm_i2c_encoder_get_client(encoder), + sil164_init_state(nouveau_i2c_encoder_get_client(encoder), &priv->config, duallink); if (priv->duallink_slave) @@ -292,7 +292,7 @@ static enum drm_connector_status sil164_encoder_detect(struct drm_encoder *encoder, struct drm_connector *connector) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder); if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT) return connector_status_connected; @@ -331,10 +331,10 @@ sil164_encoder_destroy(struct drm_encoder *encoder) i2c_unregister_device(priv->duallink_slave); kfree(priv); - drm_i2c_encoder_destroy(encoder); + nouveau_i2c_encoder_destroy(encoder); } -static const struct drm_encoder_slave_funcs sil164_encoder_funcs = { +static const struct nouveau_i2c_encoder_funcs sil164_encoder_funcs = { .set_config = sil164_encoder_set_config, .destroy = sil164_encoder_destroy, .dpms = sil164_encoder_dpms, @@ -394,7 +394,7 @@ sil164_detect_slave(struct i2c_client *client) static int sil164_encoder_init(struct i2c_client *client, struct drm_device *dev, - struct drm_encoder_slave *encoder) + struct nouveau_i2c_encoder *encoder) { struct sil164_priv *priv; struct i2c_client *slave_client; @@ -403,8 +403,8 @@ sil164_encoder_init(struct i2c_client *client, if (!priv) return -ENOMEM; - encoder->slave_priv = priv; - encoder->slave_funcs = &sil164_encoder_funcs; + encoder->encoder_i2c_priv = priv; + encoder->encoder_i2c_funcs = &sil164_encoder_funcs; slave_client = sil164_detect_slave(client); if (!IS_ERR(slave_client)) @@ -419,7 +419,7 @@ static const struct i2c_device_id sil164_ids[] = { }; MODULE_DEVICE_TABLE(i2c, sil164_ids); -static struct drm_i2c_encoder_driver sil164_driver = { +static struct nouveau_i2c_encoder_driver sil164_driver = { .i2c_driver = { .probe = sil164_probe, .driver = { @@ -435,13 +435,13 @@ static struct drm_i2c_encoder_driver sil164_driver = { static int __init sil164_init(void) { - return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver); + return i2c_add_driver(&sil164_driver.i2c_driver); } static void __exit sil164_exit(void) { - drm_i2c_encoder_unregister(&sil164_driver); + i2c_del_driver(&sil164_driver.i2c_driver); } MODULE_AUTHOR("Francisco Jerez "); diff --git a/drivers/gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c b/drivers/gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c new file mode 100644 index 000000000000..e2bf99c43336 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 + +#include + +/** + * nouveau_i2c_encoder_init - Initialize an I2C slave encoder + * @dev: DRM device. + * @encoder: Encoder to be attached to the I2C device. You aren't + * required to have called drm_encoder_init() before. + * @adap: I2C adapter that will be used to communicate with + * the device. + * @info: Information that will be used to create the I2C device. + * Required fields are @addr and @type. + * + * Create an I2C device on the specified bus (the module containing its + * driver is transparently loaded) and attach it to the specified + * &nouveau_i2c_encoder. The @encoder_i2c_funcs field will be initialized with + * the hooks provided by the slave driver. + * + * If @info.platform_data is non-NULL it will be used as the initial + * slave config. + * + * Returns 0 on success or a negative errno on failure, in particular, + * -ENODEV is returned when no matching driver is found. + */ +int nouveau_i2c_encoder_init(struct drm_device *dev, + struct nouveau_i2c_encoder *encoder, + struct i2c_adapter *adap, + const struct i2c_board_info *info) +{ + struct module *module = NULL; + struct i2c_client *client; + struct nouveau_i2c_encoder_driver *encoder_drv; + int err = 0; + + request_module("%s%s", I2C_MODULE_PREFIX, info->type); + + client = i2c_new_client_device(adap, info); + if (!i2c_client_has_driver(client)) { + err = -ENODEV; + goto fail_unregister; + } + + module = client->dev.driver->owner; + if (!try_module_get(module)) { + err = -ENODEV; + goto fail_unregister; + } + + encoder->i2c_client = client; + + encoder_drv = to_nouveau_i2c_encoder_driver(to_i2c_driver(client->dev.driver)); + + err = encoder_drv->encoder_init(client, dev, encoder); + if (err) + goto fail_module_put; + + if (info->platform_data) + encoder->encoder_i2c_funcs->set_config(&encoder->base, + info->platform_data); + + return 0; + +fail_module_put: + module_put(module); +fail_unregister: + i2c_unregister_device(client); + return err; +} + +/** + * nouveau_i2c_encoder_destroy - Unregister the I2C device backing an encoder + * @drm_encoder: Encoder to be unregistered. + * + * This should be called from the @destroy method of an I2C slave + * encoder driver once I2C access is no longer needed. + */ +void nouveau_i2c_encoder_destroy(struct drm_encoder *drm_encoder) +{ + struct nouveau_i2c_encoder *encoder = to_encoder_i2c(drm_encoder); + struct i2c_client *client = nouveau_i2c_encoder_get_client(drm_encoder); + struct module *module = client->dev.driver->owner; + + i2c_unregister_device(client); + encoder->i2c_client = NULL; + + module_put(module); +} +EXPORT_SYMBOL(nouveau_i2c_encoder_destroy); + +/* + * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs: + */ + +bool nouveau_i2c_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + if (!get_encoder_i2c_funcs(encoder)->mode_fixup) + return true; + + return get_encoder_i2c_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode); +} + +enum drm_connector_status nouveau_i2c_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + return get_encoder_i2c_funcs(encoder)->detect(encoder, connector); +} + +void nouveau_i2c_encoder_save(struct drm_encoder *encoder) +{ + get_encoder_i2c_funcs(encoder)->save(encoder); +} + +void nouveau_i2c_encoder_restore(struct drm_encoder *encoder) +{ + get_encoder_i2c_funcs(encoder)->restore(encoder); +} diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index 4ffd8af6bf8b..c61ab083f62e 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -99,7 +99,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); - get_slave_funcs(encoder)->dpms(encoder, mode); + get_encoder_i2c_funcs(encoder)->dpms(encoder, mode); } static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) @@ -158,7 +158,7 @@ static void nv04_tv_mode_set(struct drm_encoder *encoder, regp->tv_vskew = 1; regp->tv_vsync_delay = 1; - get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); + get_encoder_i2c_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); } static void nv04_tv_commit(struct drm_encoder *encoder) @@ -178,7 +178,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) static void nv04_tv_destroy(struct drm_encoder *encoder) { - get_slave_funcs(encoder)->destroy(encoder); + get_encoder_i2c_funcs(encoder)->destroy(encoder); drm_encoder_cleanup(encoder); kfree(encoder->helper_private); @@ -191,11 +191,11 @@ static const struct drm_encoder_funcs nv04_tv_funcs = { static const struct drm_encoder_helper_funcs nv04_tv_helper_funcs = { .dpms = nv04_tv_dpms, - .mode_fixup = drm_i2c_encoder_mode_fixup, + .mode_fixup = nouveau_i2c_encoder_mode_fixup, .prepare = nv04_tv_prepare, .commit = nv04_tv_commit, .mode_set = nv04_tv_mode_set, - .detect = drm_i2c_encoder_detect, + .detect = nouveau_i2c_encoder_detect, }; int @@ -226,8 +226,8 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) NULL); drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs); - nv_encoder->enc_save = drm_i2c_encoder_save; - nv_encoder->enc_restore = drm_i2c_encoder_restore; + nv_encoder->enc_save = nouveau_i2c_encoder_save; + nv_encoder->enc_restore = nouveau_i2c_encoder_restore; encoder->possible_crtcs = entry->heads; encoder->possible_clones = 0; @@ -235,14 +235,14 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) nv_encoder->or = ffs(entry->or) - 1; /* Run the slave-specific initialization */ - ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - &bus->i2c, - &nv04_tv_encoder_info[type].dev); + ret = nouveau_i2c_encoder_init(dev, to_encoder_i2c(encoder), + &bus->i2c, + &nv04_tv_encoder_info[type].dev); if (ret < 0) goto fail_cleanup; /* Attach it to the specified connector. */ - get_slave_funcs(encoder)->create_resources(encoder, connector); + get_encoder_i2c_funcs(encoder)->create_resources(encoder, connector); drm_connector_attach_encoder(connector, encoder); return 0; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 35ad4e10d273..06de05fe5db6 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -779,7 +779,7 @@ static const struct drm_encoder_helper_funcs nv17_tv_helper_funcs = { .detect = nv17_tv_detect, }; -static const struct drm_encoder_slave_funcs nv17_tv_slave_funcs = { +static const struct nouveau_i2c_encoder_funcs nv17_tv_encoder_i2c_funcs = { .get_modes = nv17_tv_get_modes, .mode_valid = nv17_tv_mode_valid, .create_resources = nv17_tv_create_resources, @@ -818,7 +818,7 @@ nv17_tv_create(struct drm_connector *connector, struct dcb_output *entry) drm_encoder_init(dev, encoder, &nv17_tv_funcs, DRM_MODE_ENCODER_TVDAC, NULL); drm_encoder_helper_add(encoder, &nv17_tv_helper_funcs); - to_encoder_slave(encoder)->slave_funcs = &nv17_tv_slave_funcs; + to_encoder_i2c(encoder)->encoder_i2c_funcs = &nv17_tv_encoder_i2c_funcs; tv_enc->base.enc_save = nv17_tv_save; tv_enc->base.enc_restore = nv17_tv_restore; diff --git a/drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h new file mode 100644 index 000000000000..31334aa90781 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * 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 THE COPYRIGHT OWNER(S) 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 __NOUVEAU_ENCODER_I2C_H__ +#define __NOUVEAU_ENCODER_I2C_H__ + +#include + +#include +#include + +/** + * struct nouveau_i2c_encoder_funcs - Entry points exposed by a I2C encoder driver + * + * Most of its members are analogous to the function pointers in + * &drm_encoder_helper_funcs and they can optionally be used to + * initialize the latter. Connector-like methods (e.g. @get_modes and + * @set_property) will typically be wrapped around and only be called + * if the encoder is the currently selected one for the connector. + */ +struct nouveau_i2c_encoder_funcs { + /** + * @set_config: Initialize any encoder-specific modesetting parameters. + * The meaning of the @params parameter is implementation dependent. It + * will usually be a structure with DVO port data format settings or + * timings. It's not required for the new parameters to take effect + * until the next mode is set. + */ + void (*set_config)(struct drm_encoder *encoder, + void *params); + + /** + * @destroy: Analogous to &drm_encoder_funcs @destroy callback. + */ + void (*destroy)(struct drm_encoder *encoder); + + /** + * @dpms: Analogous to &drm_encoder_helper_funcs @dpms callback. + */ + void (*dpms)(struct drm_encoder *encoder, int mode); + + /** + * @save: Save state. Wrapped by nouveau_i2c_encoder_save(). + */ + void (*save)(struct drm_encoder *encoder); + + /** + * @restore: Restore state. Wrapped by nouveau_i2c_encoder_restore(). + */ + void (*restore)(struct drm_encoder *encoder); + + /** + * @mode_fixup: Analogous to &drm_encoder_helper_funcs @mode_fixup + * callback. Wrapped by nouveau_i2c_encoder_mode_fixup(). + */ + bool (*mode_fixup)(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + + /** + * @mode_valid: Analogous to &drm_encoder_helper_funcs @mode_valid. + */ + int (*mode_valid)(struct drm_encoder *encoder, + const struct drm_display_mode *mode); + /** + * @mode_set: Analogous to &drm_encoder_helper_funcs @mode_set + * callback. + */ + void (*mode_set)(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + + /** + * @detect: Analogous to &drm_encoder_helper_funcs @detect + * callback. Wrapped by nouveau_i2c_encoder_detect(). + */ + enum drm_connector_status (*detect)(struct drm_encoder *encoder, + struct drm_connector *connector); + /** + * @get_modes: Get modes. + */ + int (*get_modes)(struct drm_encoder *encoder, + struct drm_connector *connector); + /** + * @create_resources: Create resources. + */ + int (*create_resources)(struct drm_encoder *encoder, + struct drm_connector *connector); + /** + * @set_property: Set property. + */ + int (*set_property)(struct drm_encoder *encoder, + struct drm_connector *connector, + struct drm_property *property, + uint64_t val); +}; + +/** + * struct nouveau_i2c_encoder - I2C encoder struct + * + * A &nouveau_i2c_encoder has two sets of callbacks, @encoder_i2c_funcs and the + * ones in @base. The former are never actually called by the common + * CRTC code, it's just a convenience for splitting the encoder + * functions in an upper, GPU-specific layer and a (hopefully) + * GPU-agnostic lower layer: It's the GPU driver responsibility to + * call the nouveau_i2c_encoder methods when appropriate. + * + * nouveau_i2c_encoder_init() provides a way to get an implementation of + * this. + */ +struct nouveau_i2c_encoder { + /** + * @base: DRM encoder object. + */ + struct drm_encoder base; + + /** + * @encoder_i2c_funcs: I2C encoder callbacks. + */ + const struct nouveau_i2c_encoder_funcs *encoder_i2c_funcs; + + /** + * @encoder_i2c_priv: I2C encoder private data. + */ + void *encoder_i2c_priv; + + /** + * @i2c_client: corresponding I2C client structure + */ + struct i2c_client *i2c_client; +}; + +#define to_encoder_i2c(x) container_of((x), struct nouveau_i2c_encoder, base) + +int nouveau_i2c_encoder_init(struct drm_device *dev, + struct nouveau_i2c_encoder *encoder, + struct i2c_adapter *adap, + const struct i2c_board_info *info); + +static inline const struct nouveau_i2c_encoder_funcs * +get_encoder_i2c_funcs(struct drm_encoder *enc) +{ + return to_encoder_i2c(enc)->encoder_i2c_funcs; +} + +/** + * struct nouveau_i2c_encoder_driver + * + * Describes a device driver for an encoder connected to the GPU through an I2C + * bus. + */ +struct nouveau_i2c_encoder_driver { + /** + * @i2c_driver: I2C device driver description. + */ + struct i2c_driver i2c_driver; + + /** + * @encoder_init: Callback to allocate any per-encoder data structures + * and to initialize the @encoder_i2c_funcs and (optionally) @encoder_i2c_priv + * members of @encoder. + */ + int (*encoder_init)(struct i2c_client *client, + struct drm_device *dev, + struct nouveau_i2c_encoder *encoder); + +}; + +#define to_nouveau_i2c_encoder_driver(x) container_of((x), \ + struct nouveau_i2c_encoder_driver, \ + i2c_driver) + +/** + * nouveau_i2c_encoder_get_client - Get the I2C client corresponding to an encoder + * @encoder: The encoder + */ +static inline struct i2c_client *nouveau_i2c_encoder_get_client(struct drm_encoder *encoder) +{ + return to_encoder_i2c(encoder)->i2c_client; +} + +void nouveau_i2c_encoder_destroy(struct drm_encoder *encoder); + +/* + * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs: + */ + +bool nouveau_i2c_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); +enum drm_connector_status nouveau_i2c_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector); +void nouveau_i2c_encoder_save(struct drm_encoder *encoder); +void nouveau_i2c_encoder_restore(struct drm_encoder *encoder); + + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 2d26784bde74..6fb9719d721f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -797,8 +797,10 @@ nouveau_connector_set_property(struct drm_connector *connector, property, value); if (ret) { if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV) - return get_slave_funcs(encoder)->set_property( - encoder, connector, property, value); + return get_encoder_i2c_funcs(encoder)->set_property(encoder, + connector, + property, + value); return ret; } @@ -1015,7 +1017,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) nouveau_connector_detect_depth(connector); if (nv_encoder->dcb->type == DCB_OUTPUT_TV) - ret = get_slave_funcs(encoder)->get_modes(encoder, connector); + ret = get_encoder_i2c_funcs(encoder)->get_modes(encoder, connector); if (nv_connector->type == DCB_CONNECTOR_LVDS || nv_connector->type == DCB_CONNECTOR_LVDS_SPWG || @@ -1100,7 +1102,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, max_clock = 350000; break; case DCB_OUTPUT_TV: - return get_slave_funcs(encoder)->mode_valid(encoder, mode); + return get_encoder_i2c_funcs(encoder)->mode_valid(encoder, mode); case DCB_OUTPUT_DP: return nv50_dp_mode_valid(nv_encoder, mode, NULL); default: diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 333042fc493f..dce8e5d9d496 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -31,7 +31,8 @@ #include #include -#include + +#include #include "dispnv04/disp.h" @@ -43,7 +44,7 @@ struct nouveau_connector; struct nvkm_i2c_port; struct nouveau_encoder { - struct drm_encoder_slave base; + struct nouveau_i2c_encoder base; struct dcb_output *dcb; struct nvif_outp outp; @@ -137,7 +138,7 @@ find_encoder(struct drm_connector *connector, int type); static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc) { - struct drm_encoder_slave *slave = to_encoder_slave(enc); + struct nouveau_i2c_encoder *slave = to_encoder_i2c(enc); return container_of(slave, struct nouveau_encoder, base); } @@ -147,12 +148,6 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) return &enc->base.base; } -static inline const struct drm_encoder_slave_funcs * -get_slave_funcs(struct drm_encoder *enc) -{ - return to_encoder_slave(enc)->slave_funcs; -} - /* nouveau_dp.c */ enum nouveau_dp_status { NOUVEAU_DP_NONE, diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h deleted file mode 100644 index b526643833dc..000000000000 --- a/include/drm/drm_encoder_slave.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2009 Francisco Jerez. - * 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 THE COPYRIGHT OWNER(S) 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 __DRM_ENCODER_SLAVE_H__ -#define __DRM_ENCODER_SLAVE_H__ - -#include - -#include -#include - -/** - * struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver - * - * Most of its members are analogous to the function pointers in - * &drm_encoder_helper_funcs and they can optionally be used to - * initialize the latter. Connector-like methods (e.g. @get_modes and - * @set_property) will typically be wrapped around and only be called - * if the encoder is the currently selected one for the connector. - */ -struct drm_encoder_slave_funcs { - /** - * @set_config: Initialize any encoder-specific modesetting parameters. - * The meaning of the @params parameter is implementation dependent. It - * will usually be a structure with DVO port data format settings or - * timings. It's not required for the new parameters to take effect - * until the next mode is set. - */ - void (*set_config)(struct drm_encoder *encoder, - void *params); - - /** - * @destroy: Analogous to &drm_encoder_funcs @destroy callback. - */ - void (*destroy)(struct drm_encoder *encoder); - - /** - * @dpms: Analogous to &drm_encoder_helper_funcs @dpms callback. Wrapped - * by drm_i2c_encoder_dpms(). - */ - void (*dpms)(struct drm_encoder *encoder, int mode); - - /** - * @save: Save state. Wrapped by drm_i2c_encoder_save(). - */ - void (*save)(struct drm_encoder *encoder); - - /** - * @restore: Restore state. Wrapped by drm_i2c_encoder_restore(). - */ - void (*restore)(struct drm_encoder *encoder); - - /** - * @mode_fixup: Analogous to &drm_encoder_helper_funcs @mode_fixup - * callback. Wrapped by drm_i2c_encoder_mode_fixup(). - */ - bool (*mode_fixup)(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - - /** - * @mode_valid: Analogous to &drm_encoder_helper_funcs @mode_valid. - */ - int (*mode_valid)(struct drm_encoder *encoder, - const struct drm_display_mode *mode); - /** - * @mode_set: Analogous to &drm_encoder_helper_funcs @mode_set - * callback. Wrapped by drm_i2c_encoder_mode_set(). - */ - void (*mode_set)(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - - /** - * @detect: Analogous to &drm_encoder_helper_funcs @detect - * callback. Wrapped by drm_i2c_encoder_detect(). - */ - enum drm_connector_status (*detect)(struct drm_encoder *encoder, - struct drm_connector *connector); - /** - * @get_modes: Get modes. - */ - int (*get_modes)(struct drm_encoder *encoder, - struct drm_connector *connector); - /** - * @create_resources: Create resources. - */ - int (*create_resources)(struct drm_encoder *encoder, - struct drm_connector *connector); - /** - * @set_property: Set property. - */ - int (*set_property)(struct drm_encoder *encoder, - struct drm_connector *connector, - struct drm_property *property, - uint64_t val); -}; - -/** - * struct drm_encoder_slave - Slave encoder struct - * - * A &drm_encoder_slave has two sets of callbacks, @slave_funcs and the - * ones in @base. The former are never actually called by the common - * CRTC code, it's just a convenience for splitting the encoder - * functions in an upper, GPU-specific layer and a (hopefully) - * GPU-agnostic lower layer: It's the GPU driver responsibility to - * call the slave methods when appropriate. - * - * drm_i2c_encoder_init() provides a way to get an implementation of - * this. - */ -struct drm_encoder_slave { - /** - * @base: DRM encoder object. - */ - struct drm_encoder base; - - /** - * @slave_funcs: Slave encoder callbacks. - */ - const struct drm_encoder_slave_funcs *slave_funcs; - - /** - * @slave_priv: Slave encoder private data. - */ - void *slave_priv; - - /** - * @bus_priv: Bus specific data. - */ - void *bus_priv; -}; -#define to_encoder_slave(x) container_of((x), struct drm_encoder_slave, base) - -int drm_i2c_encoder_init(struct drm_device *dev, - struct drm_encoder_slave *encoder, - struct i2c_adapter *adap, - const struct i2c_board_info *info); - - -/** - * struct drm_i2c_encoder_driver - * - * Describes a device driver for an encoder connected to the GPU through an I2C - * bus. - */ -struct drm_i2c_encoder_driver { - /** - * @i2c_driver: I2C device driver description. - */ - struct i2c_driver i2c_driver; - - /** - * @encoder_init: Callback to allocate any per-encoder data structures - * and to initialize the @slave_funcs and (optionally) @slave_priv - * members of @encoder. - */ - int (*encoder_init)(struct i2c_client *client, - struct drm_device *dev, - struct drm_encoder_slave *encoder); - -}; -#define to_drm_i2c_encoder_driver(x) container_of((x), \ - struct drm_i2c_encoder_driver, \ - i2c_driver) - -/** - * drm_i2c_encoder_get_client - Get the I2C client corresponding to an encoder - * @encoder: The encoder - */ -static inline struct i2c_client *drm_i2c_encoder_get_client(struct drm_encoder *encoder) -{ - return (struct i2c_client *)to_encoder_slave(encoder)->bus_priv; -} - -/** - * drm_i2c_encoder_register - Register an I2C encoder driver - * @owner: Module containing the driver. - * @driver: Driver to be registered. - */ -static inline int drm_i2c_encoder_register(struct module *owner, - struct drm_i2c_encoder_driver *driver) -{ - return i2c_register_driver(owner, &driver->i2c_driver); -} - -/** - * drm_i2c_encoder_unregister - Unregister an I2C encoder driver - * @driver: Driver to be unregistered. - */ -static inline void drm_i2c_encoder_unregister(struct drm_i2c_encoder_driver *driver) -{ - i2c_del_driver(&driver->i2c_driver); -} - -void drm_i2c_encoder_destroy(struct drm_encoder *encoder); - - -/* - * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs: - */ - -void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode); -bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); -void drm_i2c_encoder_prepare(struct drm_encoder *encoder); -void drm_i2c_encoder_commit(struct drm_encoder *encoder); -void drm_i2c_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); -enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder, - struct drm_connector *connector); -void drm_i2c_encoder_save(struct drm_encoder *encoder); -void drm_i2c_encoder_restore(struct drm_encoder *encoder); - - -#endif -- cgit v1.2.3-59-g8ed1b From 574f5ee2c85a00a579549d50e9fc9c6c072ee4c4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Dec 2024 15:18:46 +0100 Subject: drm/bridge: ti-sn65dsi86: Fix multiple instances Each bridge instance creates up to four auxiliary devices with different names. However, their IDs are always zero, causing duplicate filename errors when a system has multiple bridges: sysfs: cannot create duplicate filename '/bus/auxiliary/devices/ti_sn65dsi86.gpio.0' Fix this by using a unique instance ID per bridge instance. The instance ID is derived from the I2C adapter number and the bridge's I2C address, to support multiple instances on the same bus. Fixes: bf73537f411b ("drm/bridge: ti-sn65dsi86: Break GPIO and MIPI-to-eDP bridge into sub-drivers") Signed-off-by: Geert Uytterhoeven Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/7a68a0e3f927e26edca6040067fb653eb06efb79.1733840089.git.geert+renesas@glider.be --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index e4d9006b59f1..b3d617505dda 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -480,6 +480,7 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, const char *name) { struct device *dev = pdata->dev; + const struct i2c_client *client = to_i2c_client(dev); struct auxiliary_device *aux; int ret; @@ -488,6 +489,7 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, return -ENOMEM; aux->name = name; + aux->id = (client->adapter->nr << 10) | client->addr; aux->dev.parent = dev; aux->dev.release = ti_sn65dsi86_aux_device_release; device_set_of_node_from_dev(&aux->dev, dev); -- cgit v1.2.3-59-g8ed1b From 47ad90921586dbe1f37dab3f4352df8e42d2fa30 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:13 -0300 Subject: drm/i915/dmc_wl: Use enum values for enable_dmc_wl Currently, after sanitization, enable_dmc_wl will behave like a boolean parameter (enabled vs disabled). However, in upcoming changes, we will allow more values for debugging purposes. For that, let's make the sanitized value an enumeration. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-2-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 02de3ae15074..0850a7d866cc 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -50,6 +50,15 @@ #define DMC_WAKELOCK_CTL_TIMEOUT_US 5000 #define DMC_WAKELOCK_HOLD_TIME 50 +/* + * Possible non-negative values for the enable_dmc_wl param. + */ +enum { + ENABLE_DMC_WL_DISABLED, + ENABLE_DMC_WL_ENABLED, + ENABLE_DMC_WL_MAX, +}; + struct intel_dmc_wl_range { u32 start; u32 end; @@ -270,12 +279,20 @@ static bool __intel_dmc_wl_supported(struct intel_display *display) static void intel_dmc_wl_sanitize_param(struct intel_display *display) { - if (!HAS_DMC_WAKELOCK(display)) - display->params.enable_dmc_wl = 0; - else if (display->params.enable_dmc_wl >= 0) - display->params.enable_dmc_wl = !!display->params.enable_dmc_wl; - else - display->params.enable_dmc_wl = DISPLAY_VER(display) >= 30; + if (!HAS_DMC_WAKELOCK(display)) { + display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED; + } else if (display->params.enable_dmc_wl < 0) { + if (DISPLAY_VER(display) >= 30) + display->params.enable_dmc_wl = ENABLE_DMC_WL_ENABLED; + else + display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED; + } else if (display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX) { + display->params.enable_dmc_wl = ENABLE_DMC_WL_ENABLED; + } + + drm_WARN_ON(display->drm, + display->params.enable_dmc_wl < 0 || + display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX); drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d\n", display->params.enable_dmc_wl); -- cgit v1.2.3-59-g8ed1b From 81a1d1f5d275547f51849e14401264f0e8147bd8 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:14 -0300 Subject: drm/i915/dmc_wl: Show description string for enable_dmc_wl We already provide the value resulting from sanitization of enable_dmc_wl in dmesg, however the reader will need to either have the meanings memorized or look them up in the parameter's documentation. Let's make things easier by providing a short human-readable name for the parameter in dmesg. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-3-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 0850a7d866cc..af07eaa3a821 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -279,6 +279,8 @@ static bool __intel_dmc_wl_supported(struct intel_display *display) static void intel_dmc_wl_sanitize_param(struct intel_display *display) { + const char *desc; + if (!HAS_DMC_WAKELOCK(display)) { display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED; } else if (display->params.enable_dmc_wl < 0) { @@ -294,8 +296,20 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display) display->params.enable_dmc_wl < 0 || display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX); - drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d\n", - display->params.enable_dmc_wl); + switch (display->params.enable_dmc_wl) { + case ENABLE_DMC_WL_DISABLED: + desc = "disabled"; + break; + case ENABLE_DMC_WL_ENABLED: + desc = "enabled"; + break; + default: + desc = "unknown"; + break; + } + + drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d (%s)\n", + display->params.enable_dmc_wl, desc); } void intel_dmc_wl_init(struct intel_display *display) -- cgit v1.2.3-59-g8ed1b From a56d1e380d7475c154c39b08a3793a73e015589f Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:15 -0300 Subject: drm/i915/dmc_wl: Allow enable_dmc_wl=2 to mean "match any register" When debugging issues that might be related to the DMC wakelock code, it is sometimes useful to compare runs when we match any register offset vs the regular case. If issues disappear when we take the wakelock for any register, it might indicate that we are missing some offset to be tracked. Support matching any register offset with enable_dmc_wl=2. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-4-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_display_params.c | 2 +- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c index f92e4640a613..f0f388f38fa7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.c +++ b/drivers/gpu/drm/i915/display/intel_display_params.c @@ -130,7 +130,7 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, intel_display_param_named_unsafe(enable_dmc_wl, int, 0400, "Enable DMC wakelock " - "(-1=use per-chip default, 0=disabled, 1=enabled) " + "(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register) " "Default: -1"); __maybe_unused diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index af07eaa3a821..d442a150b327 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -56,6 +56,7 @@ enum { ENABLE_DMC_WL_DISABLED, ENABLE_DMC_WL_ENABLED, + ENABLE_DMC_WL_ANY_REGISTER, ENABLE_DMC_WL_MAX, }; @@ -239,10 +240,15 @@ static bool intel_dmc_wl_reg_in_range(i915_reg_t reg, return false; } -static bool intel_dmc_wl_check_range(i915_reg_t reg, u32 dc_state) +static bool intel_dmc_wl_check_range(struct intel_display *display, + i915_reg_t reg, + u32 dc_state) { const struct intel_dmc_wl_range *ranges; + if (display->params.enable_dmc_wl == ENABLE_DMC_WL_ANY_REGISTER) + return true; + /* * Check that the offset is in one of the ranges for which * registers are powered off during DC states. @@ -303,6 +309,9 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display) case ENABLE_DMC_WL_ENABLED: desc = "enabled"; break; + case ENABLE_DMC_WL_ANY_REGISTER: + desc = "match any register"; + break; default: desc = "unknown"; break; @@ -429,7 +438,8 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg) spin_lock_irqsave(&wl->lock, flags); - if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state)) + if (i915_mmio_reg_valid(reg) && + !intel_dmc_wl_check_range(display, reg, wl->dc_state)) goto out_unlock; if (!wl->enabled) { @@ -461,7 +471,8 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg) spin_lock_irqsave(&wl->lock, flags); - if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state)) + if (i915_mmio_reg_valid(reg) && + !intel_dmc_wl_check_range(display, reg, wl->dc_state)) goto out_unlock; if (WARN_RATELIMIT(!refcount_read(&wl->refcount), -- cgit v1.2.3-59-g8ed1b From 34e47bdbad0353acaf1eeecea64ffa711061b65c Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:16 -0300 Subject: drm/i915/dmc_wl: Allow enable_dmc_wl=3 to mean "always locked" When debugging issues that might be related to the DMC wakelock code, it might be useful to compare runs with the lock acquired while DC states are enabled vs the regular case. If issues disappear with the former, it might be a symptom of something wrong in our code. Support having this "always locked" behavior with enable_dmc_wl=3. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-5-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_display_params.c | 2 +- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c index f0f388f38fa7..c4f1ab43fc0c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.c +++ b/drivers/gpu/drm/i915/display/intel_display_params.c @@ -130,7 +130,7 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, intel_display_param_named_unsafe(enable_dmc_wl, int, 0400, "Enable DMC wakelock " - "(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register) " + "(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register, 3=always locked) " "Default: -1"); __maybe_unused diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index d442a150b327..1bdc08e6aa45 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -57,6 +57,7 @@ enum { ENABLE_DMC_WL_DISABLED, ENABLE_DMC_WL_ENABLED, ENABLE_DMC_WL_ANY_REGISTER, + ENABLE_DMC_WL_ALWAYS_LOCKED, ENABLE_DMC_WL_MAX, }; @@ -312,6 +313,9 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display) case ENABLE_DMC_WL_ANY_REGISTER: desc = "match any register"; break; + case ENABLE_DMC_WL_ALWAYS_LOCKED: + desc = "always locked"; + break; default: desc = "unknown"; break; @@ -332,7 +336,8 @@ void intel_dmc_wl_init(struct intel_display *display) INIT_DELAYED_WORK(&wl->work, intel_dmc_wl_work); spin_lock_init(&wl->lock); - refcount_set(&wl->refcount, 0); + refcount_set(&wl->refcount, + display->params.enable_dmc_wl == ENABLE_DMC_WL_ALWAYS_LOCKED ? 1 : 0); } /* Must only be called as part of enabling dynamic DC states. */ -- cgit v1.2.3-59-g8ed1b From 7e182cb4f5567f53417b762ec0d679f0b6f0039d Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Wed, 11 Dec 2024 13:18:42 -0800 Subject: drm: allow encoder mode_set even when connectors change for crtc In certain use-cases, a CRTC could switch between two encoders and because the mode being programmed on the CRTC remains the same during this switch, the CRTC's mode_changed remains false. In such cases, the encoder's mode_set also gets skipped. Skipping mode_set on the encoder for such cases could cause an issue because even though the same CRTC mode was being used, the encoder type could have changed like the CRTC could have switched from a real time encoder to a writeback encoder OR vice-versa. Allow encoder's mode_set to happen even when connectors changed on a CRTC and not just when the mode changed. Signed-off-by: Abhinav Kumar Signed-off-by: Jessica Zhang Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20241211-abhinavk-modeset-fix-v3-1-0de4bf3e7c32@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/drm_atomic_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5186d2114a50..32902f77f00d 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1376,7 +1376,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) mode = &new_crtc_state->mode; adjusted_mode = &new_crtc_state->adjusted_mode; - if (!new_crtc_state->mode_changed) + if (!new_crtc_state->mode_changed && !new_crtc_state->connectors_changed) continue; drm_dbg_atomic(dev, "modeset on [ENCODER:%d:%s]\n", -- cgit v1.2.3-59-g8ed1b From 73d934d7b6e39a3e52586467a30ca3ff3f6f9eb4 Mon Sep 17 00:00:00 2001 From: Jessica Zhang Date: Wed, 11 Dec 2024 13:18:43 -0800 Subject: drm/tests: Add test for drm_atomic_helper_commit_modeset_disables() Add a subtest to check that modeset is called when the connector is changed Signed-off-by: Jessica Zhang Reviewed-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20241211-abhinavk-modeset-fix-v3-2-0de4bf3e7c32@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/tests/Makefile | 1 + drivers/gpu/drm/tests/drm_atomic_state_test.c | 244 ++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 drivers/gpu/drm/tests/drm_atomic_state_test.c (limited to 'drivers') diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 56dab563abd7..0109bcf7faa5 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST_HELPERS) += \ drm_kunit_helpers.o obj-$(CONFIG_DRM_KUNIT_TEST) += \ + drm_atomic_state_test.o \ drm_buddy_test.o \ drm_cmdline_parser_test.o \ drm_connector_test.o \ diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c new file mode 100644 index 000000000000..be1f78024945 --- /dev/null +++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test cases for the drm_atomic_state helpers + * + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#define DRM_TEST_ENC_0 BIT(0) +#define DRM_TEST_ENC_1 BIT(1) +#define DRM_TEST_ENC_2 BIT(2) + +#define DRM_TEST_CONN_0 BIT(0) + +static const struct drm_display_mode drm_atomic_test_mode = { + DRM_MODE("1024x768", 0, 65000, 1024, 1048, + 1184, 1344, 0, 768, 771, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) +}; + +struct drm_atomic_test_priv { + struct drm_device drm; + struct drm_plane *plane; + struct drm_crtc *crtc; + struct drm_encoder encoders[3]; + struct drm_connector connectors[2]; +}; + +static int modeset_counter; + +static void drm_test_encoder_mode_set(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + modeset_counter++; +} + +static const struct drm_encoder_helper_funcs drm_atomic_test_encoder_funcs = { + .atomic_mode_set = drm_test_encoder_mode_set, +}; + +static const struct drm_connector_funcs dummy_connector_funcs = { + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .reset = drm_atomic_helper_connector_reset, +}; + +static int drm_atomic_test_dummy_get_modes(struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, + &drm_atomic_test_mode); +} + +static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = { + .get_modes = drm_atomic_test_dummy_get_modes, +}; + +static struct drm_atomic_test_priv * +drm_atomic_test_init_drm_components(struct kunit *test, bool has_connectors) +{ + struct drm_atomic_test_priv *priv; + struct drm_encoder *enc; + struct drm_connector *conn; + struct drm_device *drm; + struct device *dev; + int ret; + + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + + priv = drm_kunit_helper_alloc_drm_device(test, dev, + struct drm_atomic_test_priv, + drm, + DRIVER_MODESET | DRIVER_ATOMIC); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + test->priv = priv; + + drm = &priv->drm; + priv->plane = drm_kunit_helper_create_primary_plane(test, drm, + NULL, + NULL, + NULL, 0, + NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane); + + priv->crtc = drm_kunit_helper_create_crtc(test, drm, + priv->plane, NULL, + NULL, + NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc); + + for (int i = 0; i < ARRAY_SIZE(priv->encoders); i++) { + enc = &priv->encoders[i]; + + ret = drmm_encoder_init(drm, enc, NULL, + DRM_MODE_ENCODER_DSI, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + enc->possible_crtcs = drm_crtc_mask(priv->crtc); + } + + priv->encoders[0].possible_clones = DRM_TEST_ENC_0 | DRM_TEST_ENC_1; + priv->encoders[1].possible_clones = DRM_TEST_ENC_0 | DRM_TEST_ENC_1; + priv->encoders[2].possible_clones = DRM_TEST_ENC_2; + + if (!has_connectors) + goto done; + + BUILD_BUG_ON(ARRAY_SIZE(priv->connectors) > ARRAY_SIZE(priv->encoders)); + + for (int i = 0; i < ARRAY_SIZE(priv->connectors); i++) { + conn = &priv->connectors[i]; + + ret = drmm_connector_init(drm, conn, &dummy_connector_funcs, + DRM_MODE_CONNECTOR_DSI, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_connector_helper_add(conn, &dummy_connector_helper_funcs); + drm_encoder_helper_add(&priv->encoders[i], + &drm_atomic_test_encoder_funcs); + + drm_connector_attach_encoder(conn, &priv->encoders[i]); + } + +done: + drm_mode_config_reset(drm); + + return priv; +} + +static int set_up_atomic_state(struct kunit *test, + struct drm_atomic_test_priv *priv, + struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_device *drm = &priv->drm; + struct drm_crtc *crtc = priv->crtc; + struct drm_atomic_state *state; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + int ret; + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + if (connector) { + conn_state = drm_atomic_get_connector_state(state, connector); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); + KUNIT_EXPECT_EQ(test, ret, 0); + } + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + ret = drm_atomic_set_mode_for_crtc(crtc_state, &drm_atomic_test_mode); + KUNIT_EXPECT_EQ(test, ret, 0); + + crtc_state->enable = true; + crtc_state->active = true; + + if (connector) { + ret = drm_atomic_commit(state); + KUNIT_ASSERT_EQ(test, ret, 0); + } else { + // dummy connector mask + crtc_state->connector_mask = DRM_TEST_CONN_0; + } + + return 0; +} + +/* + * Test that the DRM encoder mode_set() is called when the atomic state + * connectors are changed but the CRTC mode is not. + */ +static void drm_test_check_connector_changed_modeset(struct kunit *test) +{ + struct drm_atomic_test_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector *old_conn, *new_conn; + struct drm_atomic_state *state; + struct drm_device *drm; + struct drm_connector_state *new_conn_state, *old_conn_state; + int ret, initial_modeset_count; + + priv = drm_atomic_test_init_drm_components(test, true); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + old_conn = &priv->connectors[0]; + new_conn = &priv->connectors[1]; + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + // first modeset to enable + ret = set_up_atomic_state(test, priv, old_conn, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + new_conn_state = drm_atomic_get_connector_state(state, new_conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + old_conn_state = drm_atomic_get_connector_state(state, old_conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + ret = drm_atomic_set_crtc_for_connector(old_conn_state, NULL); + KUNIT_EXPECT_EQ(test, ret, 0); + + ret = drm_atomic_set_crtc_for_connector(new_conn_state, priv->crtc); + KUNIT_EXPECT_EQ(test, ret, 0); + + initial_modeset_count = modeset_counter; + + // modeset_disables is called as part of the atomic commit tail + ret = drm_atomic_commit(state); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_ASSERT_EQ(test, modeset_counter, initial_modeset_count + 1); +} + +static struct kunit_case drm_test_check_modeset_test[] = { + KUNIT_CASE(drm_test_check_connector_changed_modeset), + {} +}; + +static struct kunit_suite drm_test_check_modeset_test_suite = { + .name = "drm_validate_modeset", + .test_cases = drm_test_check_modeset_test, +}; + +kunit_test_suite(drm_test_check_modeset_test_suite); + +MODULE_AUTHOR("Jessica Zhang Date: Mon, 16 Dec 2024 16:43:12 -0800 Subject: drm: add clone mode check for CRTC Add a common helper to check if the given CRTC state is in clone mode. This can be used by drivers to help detect if a CRTC is being shared by multiple encoders Signed-off-by: Jessica Zhang Reviewed-by: Abhinav Kumar Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20241216-concurrent-wb-v4-1-fe220297a7f0@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/drm_crtc.c | 20 ++++++++++++++++++++ include/drm/drm_crtc.h | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3488ff067c69..46655339003d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -939,3 +939,23 @@ int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc, return 0; } EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property); + +/** + * drm_crtc_in_clone_mode - check if the given CRTC state is in clone mode + * + * @crtc_state: CRTC state to check + * + * This function determines if the given CRTC state is being cloned by multiple + * encoders. + * + * RETURNS: + * True if the CRTC state is in clone mode. False otherwise + */ +bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state) +{ + if (!crtc_state) + return false; + + return hweight32(crtc_state->encoder_mask) > 1; +} +EXPORT_SYMBOL(drm_crtc_in_clone_mode); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 8b48a1974da3..caa56e039da2 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1323,5 +1323,5 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev, int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc, unsigned int supported_filters); - +bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state); #endif /* __DRM_CRTC_H__ */ -- cgit v1.2.3-59-g8ed1b From 5a6e8c369486a79493ab300a1987cc6aad16cf6a Mon Sep 17 00:00:00 2001 From: Jessica Zhang Date: Mon, 16 Dec 2024 16:43:13 -0800 Subject: drm/tests: Add test for drm_crtc_in_clone_mode() Add kunit test to validate drm_crtc_in_clone_mode() helper Signed-off-by: Jessica Zhang Reviewed-by: Abhinav Kumar Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20241216-concurrent-wb-v4-2-fe220297a7f0@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/tests/drm_atomic_state_test.c | 62 ++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c index be1f78024945..79bc5a9aedbf 100644 --- a/drivers/gpu/drm/tests/drm_atomic_state_test.c +++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c @@ -17,6 +17,12 @@ #define DRM_TEST_CONN_0 BIT(0) +struct drm_clone_mode_test { + const char *name; + u32 encoder_mask; + int expected_result; +}; + static const struct drm_display_mode drm_atomic_test_mode = { DRM_MODE("1024x768", 0, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, @@ -227,17 +233,71 @@ static void drm_test_check_connector_changed_modeset(struct kunit *test) KUNIT_ASSERT_EQ(test, modeset_counter, initial_modeset_count + 1); } +/* + * Test that the drm_crtc_in_clone_mode() helper can detect if a given CRTC + * state is in clone mode + */ +static void drm_test_check_in_clone_mode(struct kunit *test) +{ + bool ret; + const struct drm_clone_mode_test *param = test->param_value; + struct drm_crtc_state *crtc_state; + + crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, crtc_state); + + crtc_state->encoder_mask = param->encoder_mask; + + ret = drm_crtc_in_clone_mode(crtc_state); + + KUNIT_ASSERT_EQ(test, ret, param->expected_result); +} + +static void drm_check_in_clone_mode_desc(const struct drm_clone_mode_test *t, + char *desc) +{ + sprintf(desc, "%s", t->name); +} + +static const struct drm_clone_mode_test drm_clone_mode_tests[] = { + { + .name = "in_clone_mode", + .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_1, + .expected_result = true, + }, + { + .name = "not_in_clone_mode", + .encoder_mask = DRM_TEST_ENC_0, + .expected_result = false, + }, +}; + +KUNIT_ARRAY_PARAM(drm_check_in_clone_mode, drm_clone_mode_tests, + drm_check_in_clone_mode_desc); + static struct kunit_case drm_test_check_modeset_test[] = { KUNIT_CASE(drm_test_check_connector_changed_modeset), {} }; +static struct kunit_case drm_in_clone_mode_check_test[] = { + KUNIT_CASE_PARAM(drm_test_check_in_clone_mode, + drm_check_in_clone_mode_gen_params), + {} +}; + static struct kunit_suite drm_test_check_modeset_test_suite = { .name = "drm_validate_modeset", .test_cases = drm_test_check_modeset_test, }; -kunit_test_suite(drm_test_check_modeset_test_suite); +static struct kunit_suite drm_in_clone_mode_check_test_suite = { + .name = "drm_validate_clone_mode", + .test_cases = drm_in_clone_mode_check_test, +}; + +kunit_test_suites(&drm_in_clone_mode_check_test_suite, + &drm_test_check_modeset_test_suite); MODULE_AUTHOR("Jessica Zhang Date: Mon, 16 Dec 2024 16:43:14 -0800 Subject: drm: Add valid clones check Check that all encoders attached to a given CRTC are valid possible_clones of each other. Signed-off-by: Jessica Zhang Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20241216-concurrent-wb-v4-3-fe220297a7f0@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/drm_atomic_helper.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 32902f77f00d..40e4e1b6c911 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -574,6 +574,30 @@ mode_valid(struct drm_atomic_state *state) return 0; } +static int drm_atomic_check_valid_clones(struct drm_atomic_state *state, + struct drm_crtc *crtc) +{ + struct drm_encoder *drm_enc; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, + crtc); + + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) { + if (!drm_enc->possible_clones) { + DRM_DEBUG("enc%d possible_clones is 0\n", drm_enc->base.id); + continue; + } + + if ((crtc_state->encoder_mask & drm_enc->possible_clones) != + crtc_state->encoder_mask) { + DRM_DEBUG("crtc%d failed valid clone check for mask 0x%x\n", + crtc->base.id, crtc_state->encoder_mask); + return -EINVAL; + } + } + + return 0; +} + /** * drm_atomic_helper_check_modeset - validate state object for modeset changes * @dev: DRM device @@ -745,6 +769,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, ret = drm_atomic_add_affected_planes(state, crtc); if (ret != 0) return ret; + + ret = drm_atomic_check_valid_clones(state, crtc); + if (ret != 0) + return ret; } /* -- cgit v1.2.3-59-g8ed1b From 88849f24e2abba8a8951aa76ea60a72fba916afe Mon Sep 17 00:00:00 2001 From: Jessica Zhang Date: Mon, 16 Dec 2024 16:43:15 -0800 Subject: drm/tests: Add test for drm_atomic_helper_check_modeset() Add a test for drm_atomic_check_modeset() specifically to validate drm_atomic_check_valid_clones() helper Signed-off-by: Jessica Zhang Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20241216-concurrent-wb-v4-4-fe220297a7f0@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/tests/drm_atomic_state_test.c | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c index 79bc5a9aedbf..0ab5d9ec4a75 100644 --- a/drivers/gpu/drm/tests/drm_atomic_state_test.c +++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c @@ -253,12 +253,59 @@ static void drm_test_check_in_clone_mode(struct kunit *test) KUNIT_ASSERT_EQ(test, ret, param->expected_result); } +/* + * Test that the atomic commit path will succeed for valid clones (or non-cloned + * states) and fail for states where the cloned encoders are not possible_clones + * of each other. + */ +static void drm_test_check_valid_clones(struct kunit *test) +{ + int ret; + const struct drm_clone_mode_test *param = test->param_value; + struct drm_atomic_test_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_device *drm; + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + + priv = drm_atomic_test_init_drm_components(test, false); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ret = set_up_atomic_state(test, priv, NULL, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + crtc_state = drm_atomic_get_crtc_state(state, priv->crtc); + KUNIT_ASSERT_NOT_NULL(test, crtc_state); + + crtc_state->encoder_mask = param->encoder_mask; + + // force modeset + crtc_state->mode_changed = true; + + ret = drm_atomic_helper_check_modeset(drm, state); + KUNIT_ASSERT_EQ(test, ret, param->expected_result); +} + static void drm_check_in_clone_mode_desc(const struct drm_clone_mode_test *t, char *desc) { sprintf(desc, "%s", t->name); } +static void drm_check_valid_clones_desc(const struct drm_clone_mode_test *t, + char *desc) +{ + sprintf(desc, "%s", t->name); +} + static const struct drm_clone_mode_test drm_clone_mode_tests[] = { { .name = "in_clone_mode", @@ -272,9 +319,31 @@ static const struct drm_clone_mode_test drm_clone_mode_tests[] = { }, }; +static const struct drm_clone_mode_test drm_valid_clone_mode_tests[] = { + { + .name = "not_in_clone_mode", + .encoder_mask = DRM_TEST_ENC_0, + .expected_result = 0, + }, + + { + .name = "valid_clone", + .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_1, + .expected_result = 0, + }, + { + .name = "invalid_clone", + .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_2, + .expected_result = -EINVAL, + }, +}; + KUNIT_ARRAY_PARAM(drm_check_in_clone_mode, drm_clone_mode_tests, drm_check_in_clone_mode_desc); +KUNIT_ARRAY_PARAM(drm_check_valid_clones, drm_valid_clone_mode_tests, + drm_check_valid_clones_desc); + static struct kunit_case drm_test_check_modeset_test[] = { KUNIT_CASE(drm_test_check_connector_changed_modeset), {} @@ -283,6 +352,8 @@ static struct kunit_case drm_test_check_modeset_test[] = { static struct kunit_case drm_in_clone_mode_check_test[] = { KUNIT_CASE_PARAM(drm_test_check_in_clone_mode, drm_check_in_clone_mode_gen_params), + KUNIT_CASE_PARAM(drm_test_check_valid_clones, + drm_check_valid_clones_gen_params), {} }; -- cgit v1.2.3-59-g8ed1b From e995bb4adc728345d6c988efff36f4933e662703 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Jan 2025 20:22:40 +0200 Subject: drm/i915/gvt: store virtual_dp_monitor_edid in rodata The virtual DP EDID isn't modified. Add const modifier to store it in rodata. Reviewed-by: Nemesa Garg Reviewed-by: Zhi Wang Link: https://patchwork.freedesktop.org/patch/msgid/20250107182240.1765311-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gvt/display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 95570cabdf27..c98dfcc3d0de 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -97,7 +97,7 @@ int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) return 0; } -static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { +static const unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { { /* EDID with 1024x768 as its resolution */ /*Header*/ -- cgit v1.2.3-59-g8ed1b From 5d40d4fae6f2fb789f48207a9d4772bbee970b5c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 31 Dec 2024 12:44:58 +0100 Subject: drm/ssd130x: Set SPI .id_table to prevent an SPI core warning The only reason for the ssd130x-spi driver to have an spi_device_id table is that the SPI core always reports an "spi:" MODALIAS, even when the SPI device has been registered via a Device Tree Blob. Without spi_device_id table information in the module's metadata, module autoloading would not work because there won't be an alias that matches the MODALIAS reported by the SPI core. This spi_device_id table is not needed for device matching though, since the of_device_id table is always used in this case. For this reason, the struct spi_driver .id_table member is currently not set in the SPI driver. Because the spi_device_id table is always required for module autoloading, the SPI core checks during driver registration that both an of_device_id table and a spi_device_id table are present and that they contain the same entries for all the SPI devices. Not setting the .id_table member in the driver then confuses the core and leads to the following warning when the ssd130x-spi driver is registered: [ 41.091198] SPI driver ssd130x-spi has no spi_device_id for sinowealth,sh1106 [ 41.098614] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1305 [ 41.105862] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1306 [ 41.113062] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1307 [ 41.120247] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1309 [ 41.127449] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1322 [ 41.134627] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1325 [ 41.141784] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1327 [ 41.149021] SPI driver ssd130x-spi has no spi_device_id for solomon,ssd1331 To prevent the warning, set the .id_table even though it's not necessary. Since the check is done even for built-in drivers, drop the condition to only define the ID table when the driver is built as a module. Finally, rename the variable to use the "_spi_id" convention used for ID tables. Fixes: 74373977d2ca ("drm/solomon: Add SSD130x OLED displays SPI support") Reviewed-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20241231114516.2063201-1-javierm@redhat.com Signed-off-by: Javier Martinez Canillas --- drivers/gpu/drm/solomon/ssd130x-spi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c index 08334be38694..7c935870f7d2 100644 --- a/drivers/gpu/drm/solomon/ssd130x-spi.c +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c @@ -151,7 +151,6 @@ static const struct of_device_id ssd130x_of_match[] = { }; MODULE_DEVICE_TABLE(of, ssd130x_of_match); -#if IS_MODULE(CONFIG_DRM_SSD130X_SPI) /* * The SPI core always reports a MODALIAS uevent of the form "spi:", even * if the device was registered via OF. This means that the module will not be @@ -160,7 +159,7 @@ MODULE_DEVICE_TABLE(of, ssd130x_of_match); * To workaround this issue, add a SPI device ID table. Even when this should * not be needed for this driver to match the registered SPI devices. */ -static const struct spi_device_id ssd130x_spi_table[] = { +static const struct spi_device_id ssd130x_spi_id[] = { /* ssd130x family */ { "sh1106", SH1106_ID }, { "ssd1305", SSD1305_ID }, @@ -175,14 +174,14 @@ static const struct spi_device_id ssd130x_spi_table[] = { { "ssd1331", SSD1331_ID }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(spi, ssd130x_spi_table); -#endif +MODULE_DEVICE_TABLE(spi, ssd130x_spi_id); static struct spi_driver ssd130x_spi_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = ssd130x_of_match, }, + .id_table = ssd130x_spi_id, .probe = ssd130x_spi_probe, .remove = ssd130x_spi_remove, .shutdown = ssd130x_spi_shutdown, -- cgit v1.2.3-59-g8ed1b From 3566784817aeb1a733c95953998a29adc386d2ff Mon Sep 17 00:00:00 2001 From: Ravi Kumar Vodapalli Date: Thu, 9 Jan 2025 01:32:10 +0530 Subject: drm/i915/display: Update DBUF_TRACKER_STATE_SERVICE only on appropriate platforms The bspec only asks the driver to reprogram the DBUF_CTL's DBUF_TRACKER_STATE_SERVICE field to 0x8 on DG2 and platforms with display version 12. All other platforms should avoid reprogramming this register at driver init. Although we've been accidentally reprogramming DBUF_CTL on platforms where the spec does not ask us to, that mistake has been harmless so far because the value being programmed by the driver happened to match the hardware's default settings. So, update DBUF_TRACKER_STATE_SERVICE field to 0x8 only for 1. display version 12 2. DG2. Other platforms unless stated should use their default value. Bspec: 49213 Signed-off-by: Ravi Kumar Vodapalli Reviewed-by: Jonathan Cavitt Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20250108200210.1815229-1-ravi.kumar.vodapalli@intel.com [mattrope: Tweaked patch subject to accurately reflect content] Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_display_power.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index d3b8453a1705..8e86fcbcc189 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1126,9 +1126,6 @@ static void gen12_dbuf_slices_config(struct intel_display *display) { enum dbuf_slice slice; - if (display->platform.alderlake_p) - return; - for_each_dbuf_slice(display, slice) intel_de_rmw(display, DBUF_CTL_S(slice), DBUF_TRACKER_STATE_SERVICE_MASK, @@ -1681,7 +1678,7 @@ static void icl_display_core_init(struct intel_display *display, /* 4. Enable CDCLK. */ intel_cdclk_init_hw(display); - if (DISPLAY_VER(display) >= 12) + if (DISPLAY_VER(display) == 12 || display->platform.dg2) gen12_dbuf_slices_config(display); /* 5. Enable DBUF. */ -- cgit v1.2.3-59-g8ed1b From 950942b4813f8c44dbec683fdb140cf4a238516b Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:24 +0100 Subject: accel/ivpu: Separate DB ID and CMDQ ID allocations from CMDQ allocation Move doorbell ID and command queue ID XArray allocations from command queue memory allocation function. This will allow ID allocations to be done without the need for actual memory allocation. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-2-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_job.c | 88 +++++++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index 7149312f16e1..98e53cb38ecd 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -83,23 +83,9 @@ static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv) if (!cmdq) return NULL; - ret = xa_alloc_cyclic(&vdev->db_xa, &cmdq->db_id, NULL, vdev->db_limit, &vdev->db_next, - GFP_KERNEL); - if (ret < 0) { - ivpu_err(vdev, "Failed to allocate doorbell id: %d\n", ret); - goto err_free_cmdq; - } - - ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &cmdq->id, cmdq, file_priv->cmdq_limit, - &file_priv->cmdq_id_next, GFP_KERNEL); - if (ret < 0) { - ivpu_err(vdev, "Failed to allocate command queue id: %d\n", ret); - goto err_erase_db_xa; - } - cmdq->mem = ivpu_bo_create_global(vdev, SZ_4K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE); if (!cmdq->mem) - goto err_erase_cmdq_xa; + goto err_free_cmdq; ret = ivpu_preemption_buffers_create(vdev, file_priv, cmdq); if (ret) @@ -107,10 +93,6 @@ static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv) return cmdq; -err_erase_cmdq_xa: - xa_erase(&file_priv->cmdq_xa, cmdq->id); -err_erase_db_xa: - xa_erase(&vdev->db_xa, cmdq->db_id); err_free_cmdq: kfree(cmdq); return NULL; @@ -233,30 +215,88 @@ static int ivpu_cmdq_fini(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cm return 0; } +static int ivpu_db_id_alloc(struct ivpu_device *vdev, u32 *db_id) +{ + int ret; + u32 id; + + ret = xa_alloc_cyclic(&vdev->db_xa, &id, NULL, vdev->db_limit, &vdev->db_next, GFP_KERNEL); + if (ret < 0) + return ret; + + *db_id = id; + return 0; +} + +static int ivpu_cmdq_id_alloc(struct ivpu_file_priv *file_priv, u32 *cmdq_id) +{ + int ret; + u32 id; + + ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &id, NULL, file_priv->cmdq_limit, + &file_priv->cmdq_id_next, GFP_KERNEL); + if (ret < 0) + return ret; + + *cmdq_id = id; + return 0; +} + static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u8 priority) { + struct ivpu_device *vdev = file_priv->vdev; struct ivpu_cmdq *cmdq; - unsigned long cmdq_id; + unsigned long id; int ret; lockdep_assert_held(&file_priv->lock); - xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) + xa_for_each(&file_priv->cmdq_xa, id, cmdq) if (cmdq->priority == priority) break; if (!cmdq) { cmdq = ivpu_cmdq_alloc(file_priv); - if (!cmdq) + if (!cmdq) { + ivpu_err(vdev, "Failed to allocate command queue\n"); return NULL; + } + + ret = ivpu_db_id_alloc(vdev, &cmdq->db_id); + if (ret) { + ivpu_err(file_priv->vdev, "Failed to allocate doorbell ID: %d\n", ret); + goto err_free_cmdq; + } + + ret = ivpu_cmdq_id_alloc(file_priv, &cmdq->id); + if (ret) { + ivpu_err(vdev, "Failed to allocate command queue ID: %d\n", ret); + goto err_erase_db_id; + } + cmdq->priority = priority; + ret = xa_err(xa_store(&file_priv->cmdq_xa, cmdq->id, cmdq, GFP_KERNEL)); + if (ret) { + ivpu_err(vdev, "Failed to store command queue in cmdq_xa: %d\n", ret); + goto err_erase_cmdq_id; + } } ret = ivpu_cmdq_init(file_priv, cmdq, priority); - if (ret) - return NULL; + if (ret) { + ivpu_err(vdev, "Failed to initialize command queue: %d\n", ret); + goto err_free_cmdq; + } return cmdq; + +err_erase_cmdq_id: + xa_erase(&file_priv->cmdq_xa, cmdq->id); +err_erase_db_id: + xa_erase(&vdev->db_xa, cmdq->db_id); +err_free_cmdq: + ivpu_cmdq_free(file_priv, cmdq); + return NULL; } void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) -- cgit v1.2.3-59-g8ed1b From 465a3914b254f82608a8dfb580ac9930722dfd88 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:25 +0100 Subject: accel/ivpu: Add API for command queue create/destroy/submit Implement support for explicit command queue management. To allow more flexible control over command queues add capabilities to create, destroy and submit jobs to specific command queues. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-3-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 6 + drivers/accel/ivpu/ivpu_job.c | 369 +++++++++++++++++++++++++----------------- drivers/accel/ivpu/ivpu_job.h | 5 +- include/uapi/drm/ivpu_accel.h | 84 ++++++++++ 4 files changed, 319 insertions(+), 145 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 1e8ffbe25eee..f4171536640b 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -137,6 +137,9 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param case DRM_IVPU_CAP_DMA_MEMORY_RANGE: args->value = 1; break; + case DRM_IVPU_CAP_MANAGE_CMDQ: + args->value = 1; + break; default: return -EINVAL; } @@ -310,6 +313,9 @@ static const struct drm_ioctl_desc ivpu_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_GET_DATA, ivpu_ms_get_data_ioctl, 0), DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_STOP, ivpu_ms_stop_ioctl, 0), DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_GET_INFO, ivpu_ms_get_info_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_CMDQ_CREATE, ivpu_cmdq_create_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_CMDQ_DESTROY, ivpu_cmdq_destroy_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_CMDQ_SUBMIT, ivpu_cmdq_submit_ioctl, 0), }; static int ivpu_wait_for_ready(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index 98e53cb38ecd..43507d3aea51 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -100,15 +100,43 @@ err_free_cmdq: static void ivpu_cmdq_free(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) { - if (!cmdq) - return; - ivpu_preemption_buffers_free(file_priv->vdev, file_priv, cmdq); ivpu_bo_free(cmdq->mem); - xa_erase(&file_priv->vdev->db_xa, cmdq->db_id); kfree(cmdq); } +static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 priority, + bool is_legacy) +{ + struct ivpu_device *vdev = file_priv->vdev; + struct ivpu_cmdq *cmdq = NULL; + int ret; + + lockdep_assert_held(&file_priv->lock); + + cmdq = ivpu_cmdq_alloc(file_priv); + if (!cmdq) { + ivpu_err(vdev, "Failed to allocate command queue\n"); + return NULL; + } + + cmdq->priority = priority; + cmdq->is_legacy = is_legacy; + + ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &cmdq->id, cmdq, file_priv->cmdq_limit, + &file_priv->cmdq_id_next, GFP_KERNEL); + if (ret < 0) { + ivpu_err(vdev, "Failed to allocate command queue ID: %d\n", ret); + goto err_free_cmdq; + } + + return cmdq; + +err_free_cmdq: + ivpu_cmdq_free(file_priv, cmdq); + return NULL; +} + static int ivpu_hws_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine, u8 priority) { @@ -134,6 +162,13 @@ static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq * struct ivpu_device *vdev = file_priv->vdev; int ret; + ret = xa_alloc_cyclic(&vdev->db_xa, &cmdq->db_id, NULL, vdev->db_limit, &vdev->db_next, + GFP_KERNEL); + if (ret < 0) { + ivpu_err(vdev, "Failed to allocate doorbell ID: %d\n", ret); + return ret; + } + if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->id, cmdq->db_id, cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); @@ -142,41 +177,52 @@ static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq * cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); if (!ret) - ivpu_dbg(vdev, JOB, "DB %d registered to cmdq %d ctx %d\n", - cmdq->db_id, cmdq->id, file_priv->ctx.id); + ivpu_dbg(vdev, JOB, "DB %d registered to cmdq %d ctx %d priority %d\n", + cmdq->db_id, cmdq->id, file_priv->ctx.id, cmdq->priority); + else + xa_erase(&vdev->db_xa, cmdq->db_id); return ret; } -static int -ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u8 priority) +static void ivpu_cmdq_jobq_init(struct ivpu_device *vdev, struct vpu_job_queue *jobq) +{ + jobq->header.engine_idx = VPU_ENGINE_COMPUTE; + jobq->header.head = 0; + jobq->header.tail = 0; + + if (ivpu_test_mode & IVPU_TEST_MODE_TURBO) { + ivpu_dbg(vdev, JOB, "Turbo mode enabled"); + jobq->header.flags = VPU_JOB_QUEUE_FLAGS_TURBO_MODE; + } + + wmb(); /* Flush WC buffer for jobq->header */ +} + +static inline u32 ivpu_cmdq_get_entry_count(struct ivpu_cmdq *cmdq) +{ + size_t size = ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header); + + return size / sizeof(struct vpu_job_queue_entry); +} + +static int ivpu_cmdq_register(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) { struct ivpu_device *vdev = file_priv->vdev; - struct vpu_job_queue_header *jobq_header; int ret; lockdep_assert_held(&file_priv->lock); - if (cmdq->db_registered) + if (cmdq->db_id) return 0; - cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) / - sizeof(struct vpu_job_queue_entry)); - + cmdq->entry_count = ivpu_cmdq_get_entry_count(cmdq); cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem); - jobq_header = &cmdq->jobq->header; - jobq_header->engine_idx = VPU_ENGINE_COMPUTE; - jobq_header->head = 0; - jobq_header->tail = 0; - if (ivpu_test_mode & IVPU_TEST_MODE_TURBO) { - ivpu_dbg(vdev, JOB, "Turbo mode enabled"); - jobq_header->flags = VPU_JOB_QUEUE_FLAGS_TURBO_MODE; - } - wmb(); /* Flush WC buffer for jobq->header */ + ivpu_cmdq_jobq_init(vdev, cmdq->jobq); if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { - ret = ivpu_hws_cmdq_init(file_priv, cmdq, VPU_ENGINE_COMPUTE, priority); + ret = ivpu_hws_cmdq_init(file_priv, cmdq, VPU_ENGINE_COMPUTE, cmdq->priority); if (ret) return ret; } @@ -185,23 +231,19 @@ ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u8 prio if (ret) return ret; - cmdq->db_registered = true; - return 0; } -static int ivpu_cmdq_fini(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) +static int ivpu_cmdq_unregister(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) { struct ivpu_device *vdev = file_priv->vdev; int ret; lockdep_assert_held(&file_priv->lock); - if (!cmdq->db_registered) + if (!cmdq->db_id) return 0; - cmdq->db_registered = false; - if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id); if (!ret) @@ -212,91 +254,61 @@ static int ivpu_cmdq_fini(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cm if (!ret) ivpu_dbg(vdev, JOB, "DB %d unregistered\n", cmdq->db_id); + xa_erase(&file_priv->vdev->db_xa, cmdq->db_id); + cmdq->db_id = 0; + return 0; } -static int ivpu_db_id_alloc(struct ivpu_device *vdev, u32 *db_id) +static inline u8 ivpu_job_to_jsm_priority(u8 priority) { - int ret; - u32 id; - - ret = xa_alloc_cyclic(&vdev->db_xa, &id, NULL, vdev->db_limit, &vdev->db_next, GFP_KERNEL); - if (ret < 0) - return ret; + if (priority == DRM_IVPU_JOB_PRIORITY_DEFAULT) + return VPU_JOB_SCHEDULING_PRIORITY_BAND_NORMAL; - *db_id = id; - return 0; + return priority - 1; } -static int ivpu_cmdq_id_alloc(struct ivpu_file_priv *file_priv, u32 *cmdq_id) +static void ivpu_cmdq_destroy(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) { - int ret; - u32 id; - - ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &id, NULL, file_priv->cmdq_limit, - &file_priv->cmdq_id_next, GFP_KERNEL); - if (ret < 0) - return ret; - - *cmdq_id = id; - return 0; + ivpu_cmdq_unregister(file_priv, cmdq); + xa_erase(&file_priv->cmdq_xa, cmdq->id); + ivpu_cmdq_free(file_priv, cmdq); } -static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u8 priority) +static struct ivpu_cmdq *ivpu_cmdq_acquire_legacy(struct ivpu_file_priv *file_priv, u8 priority) { - struct ivpu_device *vdev = file_priv->vdev; struct ivpu_cmdq *cmdq; unsigned long id; - int ret; lockdep_assert_held(&file_priv->lock); xa_for_each(&file_priv->cmdq_xa, id, cmdq) - if (cmdq->priority == priority) + if (cmdq->is_legacy && cmdq->priority == priority) break; if (!cmdq) { - cmdq = ivpu_cmdq_alloc(file_priv); - if (!cmdq) { - ivpu_err(vdev, "Failed to allocate command queue\n"); + cmdq = ivpu_cmdq_create(file_priv, priority, true); + if (!cmdq) return NULL; - } + } - ret = ivpu_db_id_alloc(vdev, &cmdq->db_id); - if (ret) { - ivpu_err(file_priv->vdev, "Failed to allocate doorbell ID: %d\n", ret); - goto err_free_cmdq; - } + return cmdq; +} - ret = ivpu_cmdq_id_alloc(file_priv, &cmdq->id); - if (ret) { - ivpu_err(vdev, "Failed to allocate command queue ID: %d\n", ret); - goto err_erase_db_id; - } +static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u32 cmdq_id) +{ + struct ivpu_device *vdev = file_priv->vdev; + struct ivpu_cmdq *cmdq; - cmdq->priority = priority; - ret = xa_err(xa_store(&file_priv->cmdq_xa, cmdq->id, cmdq, GFP_KERNEL)); - if (ret) { - ivpu_err(vdev, "Failed to store command queue in cmdq_xa: %d\n", ret); - goto err_erase_cmdq_id; - } - } + lockdep_assert_held(&file_priv->lock); - ret = ivpu_cmdq_init(file_priv, cmdq, priority); - if (ret) { - ivpu_err(vdev, "Failed to initialize command queue: %d\n", ret); - goto err_free_cmdq; + cmdq = xa_load(&file_priv->cmdq_xa, cmdq_id); + if (!cmdq) { + ivpu_err(vdev, "Failed to find command queue with ID: %u\n", cmdq_id); + return NULL; } return cmdq; - -err_erase_cmdq_id: - xa_erase(&file_priv->cmdq_xa, cmdq->id); -err_erase_db_id: - xa_erase(&vdev->db_xa, cmdq->db_id); -err_free_cmdq: - ivpu_cmdq_free(file_priv, cmdq); - return NULL; } void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) @@ -306,11 +318,8 @@ void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) lockdep_assert_held(&file_priv->lock); - xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) { - xa_erase(&file_priv->cmdq_xa, cmdq_id); - ivpu_cmdq_fini(file_priv, cmdq); - ivpu_cmdq_free(file_priv, cmdq); - } + xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) + ivpu_cmdq_destroy(file_priv, cmdq); } /* @@ -326,8 +335,10 @@ static void ivpu_cmdq_reset(struct ivpu_file_priv *file_priv) mutex_lock(&file_priv->lock); - xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) - cmdq->db_registered = false; + xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) { + xa_erase(&file_priv->vdev->db_xa, cmdq->db_id); + cmdq->db_id = 0; + } mutex_unlock(&file_priv->lock); } @@ -345,13 +356,13 @@ void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev) mutex_unlock(&vdev->context_list_lock); } -static void ivpu_cmdq_fini_all(struct ivpu_file_priv *file_priv) +static void ivpu_cmdq_unregister_all(struct ivpu_file_priv *file_priv) { struct ivpu_cmdq *cmdq; unsigned long cmdq_id; xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) - ivpu_cmdq_fini(file_priv, cmdq); + ivpu_cmdq_unregister(file_priv, cmdq); } void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) @@ -360,7 +371,7 @@ void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) lockdep_assert_held(&file_priv->lock); - ivpu_cmdq_fini_all(file_priv); + ivpu_cmdq_unregister_all(file_priv); if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS) ivpu_jsm_context_release(vdev, file_priv->ctx.id); @@ -549,7 +560,7 @@ void ivpu_jobs_abort_all(struct ivpu_device *vdev) ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED); } -static int ivpu_job_submit(struct ivpu_job *job, u8 priority) +static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) { struct ivpu_file_priv *file_priv = job->file_priv; struct ivpu_device *vdev = job->vdev; @@ -563,14 +574,22 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority) mutex_lock(&file_priv->lock); - cmdq = ivpu_cmdq_acquire(file_priv, priority); + if (cmdq_id == 0) + cmdq = ivpu_cmdq_acquire_legacy(file_priv, priority); + else + cmdq = ivpu_cmdq_acquire(file_priv, cmdq_id); if (!cmdq) { - ivpu_warn_ratelimited(vdev, "Failed to get job queue, ctx %d engine %d prio %d\n", - file_priv->ctx.id, job->engine_idx, priority); + ivpu_warn_ratelimited(vdev, "Failed to get job queue, ctx %d\n", file_priv->ctx.id); ret = -EINVAL; goto err_unlock_file_priv; } + ret = ivpu_cmdq_register(file_priv, cmdq); + if (ret) { + ivpu_err(vdev, "Failed to register command queue: %d\n", ret); + goto err_unlock_file_priv; + } + xa_lock(&vdev->submitted_jobs_xa); is_first_job = xa_empty(&vdev->submitted_jobs_xa); ret = __xa_alloc_cyclic(&vdev->submitted_jobs_xa, &job->job_id, job, file_priv->job_limit, @@ -599,7 +618,7 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority) trace_job("submit", job); ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d prio %d addr 0x%llx next %d\n", - job->job_id, file_priv->ctx.id, job->engine_idx, priority, + job->job_id, file_priv->ctx.id, job->engine_idx, cmdq->priority, job->cmd_buf_vpu_addr, cmdq->jobq->header.tail); xa_unlock(&vdev->submitted_jobs_xa); @@ -625,7 +644,7 @@ static int ivpu_job_prepare_bos_for_submit(struct drm_file *file, struct ivpu_job *job, u32 *buf_handles, u32 buf_count, u32 commands_offset) { - struct ivpu_file_priv *file_priv = file->driver_priv; + struct ivpu_file_priv *file_priv = job->file_priv; struct ivpu_device *vdev = file_priv->vdev; struct ww_acquire_ctx acquire_ctx; enum dma_resv_usage usage; @@ -687,49 +706,20 @@ unlock_reservations: return ret; } -static inline u8 ivpu_job_to_hws_priority(struct ivpu_file_priv *file_priv, u8 priority) +static int ivpu_submit(struct drm_file *file, struct ivpu_file_priv *file_priv, u32 cmdq_id, + u32 buffer_count, u32 engine, void __user *buffers_ptr, u32 cmds_offset, + u8 priority) { - if (priority == DRM_IVPU_JOB_PRIORITY_DEFAULT) - return DRM_IVPU_JOB_PRIORITY_NORMAL; - - return priority - 1; -} - -int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) -{ - struct ivpu_file_priv *file_priv = file->driver_priv; struct ivpu_device *vdev = file_priv->vdev; - struct drm_ivpu_submit *params = data; struct ivpu_job *job; u32 *buf_handles; int idx, ret; - u8 priority; - - if (params->engine != DRM_IVPU_ENGINE_COMPUTE) - return -EINVAL; - - if (params->priority > DRM_IVPU_JOB_PRIORITY_REALTIME) - return -EINVAL; - - if (params->buffer_count == 0 || params->buffer_count > JOB_MAX_BUFFER_COUNT) - return -EINVAL; - - if (!IS_ALIGNED(params->commands_offset, 8)) - return -EINVAL; - if (!file_priv->ctx.id) - return -EINVAL; - - if (file_priv->has_mmu_faults) - return -EBADFD; - - buf_handles = kcalloc(params->buffer_count, sizeof(u32), GFP_KERNEL); + buf_handles = kcalloc(buffer_count, sizeof(u32), GFP_KERNEL); if (!buf_handles) return -ENOMEM; - ret = copy_from_user(buf_handles, - (void __user *)params->buffers_ptr, - params->buffer_count * sizeof(u32)); + ret = copy_from_user(buf_handles, buffers_ptr, buffer_count * sizeof(u32)); if (ret) { ret = -EFAULT; goto err_free_handles; @@ -740,27 +730,23 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) goto err_free_handles; } - ivpu_dbg(vdev, JOB, "Submit ioctl: ctx %u buf_count %u\n", - file_priv->ctx.id, params->buffer_count); + ivpu_dbg(vdev, JOB, "Submit ioctl: ctx %u buf_count %u\n", file_priv->ctx.id, buffer_count); - job = ivpu_job_create(file_priv, params->engine, params->buffer_count); + job = ivpu_job_create(file_priv, engine, buffer_count); if (!job) { ivpu_err(vdev, "Failed to create job\n"); ret = -ENOMEM; goto err_exit_dev; } - ret = ivpu_job_prepare_bos_for_submit(file, job, buf_handles, params->buffer_count, - params->commands_offset); + ret = ivpu_job_prepare_bos_for_submit(file, job, buf_handles, buffer_count, cmds_offset); if (ret) { ivpu_err(vdev, "Failed to prepare job: %d\n", ret); goto err_destroy_job; } - priority = ivpu_job_to_hws_priority(file_priv, params->priority); - down_read(&vdev->pm->reset_lock); - ret = ivpu_job_submit(job, priority); + ret = ivpu_job_submit(job, priority, cmdq_id); up_read(&vdev->pm->reset_lock); if (ret) goto err_signal_fence; @@ -780,6 +766,101 @@ err_free_handles: return ret; } +int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct ivpu_file_priv *file_priv = file->driver_priv; + struct drm_ivpu_submit *args = data; + u8 priority; + + if (args->engine != DRM_IVPU_ENGINE_COMPUTE) + return -EINVAL; + + if (args->priority > DRM_IVPU_JOB_PRIORITY_REALTIME) + return -EINVAL; + + if (args->buffer_count == 0 || args->buffer_count > JOB_MAX_BUFFER_COUNT) + return -EINVAL; + + if (!IS_ALIGNED(args->commands_offset, 8)) + return -EINVAL; + + if (!file_priv->ctx.id) + return -EINVAL; + + if (file_priv->has_mmu_faults) + return -EBADFD; + + priority = ivpu_job_to_jsm_priority(args->priority); + + return ivpu_submit(file, file_priv, 0, args->buffer_count, args->engine, + (void __user *)args->buffers_ptr, args->commands_offset, priority); +} + +int ivpu_cmdq_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct ivpu_file_priv *file_priv = file->driver_priv; + struct drm_ivpu_cmdq_submit *args = data; + + if (args->cmdq_id < IVPU_CMDQ_MIN_ID || args->cmdq_id > IVPU_CMDQ_MAX_ID) + return -EINVAL; + + if (args->buffer_count == 0 || args->buffer_count > JOB_MAX_BUFFER_COUNT) + return -EINVAL; + + if (!IS_ALIGNED(args->commands_offset, 8)) + return -EINVAL; + + if (!file_priv->ctx.id) + return -EINVAL; + + if (file_priv->has_mmu_faults) + return -EBADFD; + + return ivpu_submit(file, file_priv, args->cmdq_id, args->buffer_count, VPU_ENGINE_COMPUTE, + (void __user *)args->buffers_ptr, args->commands_offset, 0); +} + +int ivpu_cmdq_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct ivpu_file_priv *file_priv = file->driver_priv; + struct drm_ivpu_cmdq_create *args = data; + struct ivpu_cmdq *cmdq; + + if (args->priority > DRM_IVPU_JOB_PRIORITY_REALTIME) + return -EINVAL; + + mutex_lock(&file_priv->lock); + + cmdq = ivpu_cmdq_create(file_priv, ivpu_job_to_jsm_priority(args->priority), false); + if (cmdq) + args->cmdq_id = cmdq->id; + + mutex_unlock(&file_priv->lock); + + return cmdq ? 0 : -ENOMEM; +} + +int ivpu_cmdq_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct ivpu_file_priv *file_priv = file->driver_priv; + struct drm_ivpu_cmdq_destroy *args = data; + struct ivpu_cmdq *cmdq; + int ret = 0; + + mutex_lock(&file_priv->lock); + + cmdq = xa_load(&file_priv->cmdq_xa, args->cmdq_id); + if (!cmdq || cmdq->is_legacy) { + ret = -ENOENT; + goto unlock; + } + + ivpu_cmdq_destroy(file_priv, cmdq); +unlock: + mutex_unlock(&file_priv->lock); + return ret; +} + static void ivpu_job_done_callback(struct ivpu_device *vdev, struct ivpu_ipc_hdr *ipc_hdr, struct vpu_jsm_msg *jsm_msg) diff --git a/drivers/accel/ivpu/ivpu_job.h b/drivers/accel/ivpu/ivpu_job.h index 8b19e3f8b4cf..4d31277bcc41 100644 --- a/drivers/accel/ivpu/ivpu_job.h +++ b/drivers/accel/ivpu/ivpu_job.h @@ -30,8 +30,8 @@ struct ivpu_cmdq { u32 entry_count; u32 id; u32 db_id; - bool db_registered; u8 priority; + bool is_legacy; }; /** @@ -58,6 +58,9 @@ struct ivpu_job { }; int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int ivpu_cmdq_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int ivpu_cmdq_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int ivpu_cmdq_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file); void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv); diff --git a/include/uapi/drm/ivpu_accel.h b/include/uapi/drm/ivpu_accel.h index a35b97b097bf..746c43bd3eb6 100644 --- a/include/uapi/drm/ivpu_accel.h +++ b/include/uapi/drm/ivpu_accel.h @@ -22,6 +22,9 @@ extern "C" { #define DRM_IVPU_METRIC_STREAMER_STOP 0x08 #define DRM_IVPU_METRIC_STREAMER_GET_DATA 0x09 #define DRM_IVPU_METRIC_STREAMER_GET_INFO 0x0a +#define DRM_IVPU_CMDQ_CREATE 0x0b +#define DRM_IVPU_CMDQ_DESTROY 0x0c +#define DRM_IVPU_CMDQ_SUBMIT 0x0d #define DRM_IOCTL_IVPU_GET_PARAM \ DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_GET_PARAM, struct drm_ivpu_param) @@ -57,6 +60,15 @@ extern "C" { DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_GET_INFO, \ struct drm_ivpu_metric_streamer_get_data) +#define DRM_IOCTL_IVPU_CMDQ_CREATE \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_CMDQ_CREATE, struct drm_ivpu_cmdq_create) + +#define DRM_IOCTL_IVPU_CMDQ_DESTROY \ + DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_CMDQ_DESTROY, struct drm_ivpu_cmdq_destroy) + +#define DRM_IOCTL_IVPU_CMDQ_SUBMIT \ + DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_CMDQ_SUBMIT, struct drm_ivpu_cmdq_submit) + /** * DOC: contexts * @@ -107,6 +119,13 @@ extern "C" { * accessible by hardware DMA. */ #define DRM_IVPU_CAP_DMA_MEMORY_RANGE 2 +/** + * DRM_IVPU_CAP_MANAGE_CMDQ + * + * Driver supports explicit command queue operations like command queue create, + * command queue destroy and submit job on specific command queue. + */ +#define DRM_IVPU_CAP_MANAGE_CMDQ 3 /** * struct drm_ivpu_param - Get/Set VPU parameters @@ -316,6 +335,44 @@ struct drm_ivpu_submit { __u32 priority; }; +/** + * struct drm_ivpu_cmdq_submit - Submit commands to the VPU using explicit command queue + * + * Execute a single command buffer on a given command queue. + * Handles to all referenced buffer objects have to be provided in @buffers_ptr. + * + * User space may wait on job completion using %DRM_IVPU_BO_WAIT ioctl. + */ +struct drm_ivpu_cmdq_submit { + /** + * @buffers_ptr: + * + * A pointer to an u32 array of GEM handles of the BOs required for this job. + * The number of elements in the array must be equal to the value given by @buffer_count. + * + * The first BO is the command buffer. The rest of array has to contain all + * BOs referenced from the command buffer. + */ + __u64 buffers_ptr; + + /** @buffer_count: Number of elements in the @buffers_ptr */ + __u32 buffer_count; + + /** @cmdq_id: ID for the command queue where job will be submitted */ + __u32 cmdq_id; + + /** @flags: Reserved for future use - must be zero */ + __u32 flags; + + /** + * @commands_offset: + * + * Offset inside the first buffer in @buffers_ptr containing commands + * to be executed. The offset has to be 8-byte aligned. + */ + __u32 commands_offset; +}; + /* drm_ivpu_bo_wait job status codes */ #define DRM_IVPU_JOB_STATUS_SUCCESS 0 #define DRM_IVPU_JOB_STATUS_ABORTED 256 @@ -388,6 +445,33 @@ struct drm_ivpu_metric_streamer_get_data { __u64 data_size; }; +/** + * struct drm_ivpu_cmdq_create - Create command queue for job submission + */ +struct drm_ivpu_cmdq_create { + /** @cmdq_id: Returned ID of created command queue */ + __u32 cmdq_id; + /** + * @priority: + * + * Priority to be set for related job command queue, can be one of the following: + * %DRM_IVPU_JOB_PRIORITY_DEFAULT + * %DRM_IVPU_JOB_PRIORITY_IDLE + * %DRM_IVPU_JOB_PRIORITY_NORMAL + * %DRM_IVPU_JOB_PRIORITY_FOCUS + * %DRM_IVPU_JOB_PRIORITY_REALTIME + */ + __u32 priority; +}; + +/** + * struct drm_ivpu_cmdq_destroy - Destroy a command queue + */ +struct drm_ivpu_cmdq_destroy { + /** @cmdq_id: ID of command queue to destroy */ + __u32 cmdq_id; +}; + /** * struct drm_ivpu_metric_streamer_stop - Stop collecting metric data */ -- cgit v1.2.3-59-g8ed1b From 5bbccadaf33eea2b879d8326ad59ae0663be47d1 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:26 +0100 Subject: accel/ivpu: Abort all jobs after command queue unregister With hardware scheduler it is not expected to receive JOB_DONE notifications from NPU FW for the jobs aborted due to command queue destroy JSM command. Remove jobs submitted to unregistered command queue from submitted_jobs_xa to avoid triggering a TDR in such case. Add explicit submitted_jobs_lock that protects access to list of submitted jobs which is now used to find jobs to abort. Move context abort procedure to separate work queue not to slow down handling of IPCs or DCT requests in case where job abort takes longer, especially when destruction of the last job of a specific context results in context release. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-4-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 32 ++-------- drivers/accel/ivpu/ivpu_drv.h | 2 + drivers/accel/ivpu/ivpu_job.c | 137 ++++++++++++++++++++++++++++++---------- drivers/accel/ivpu/ivpu_job.h | 4 ++ drivers/accel/ivpu/ivpu_mmu.c | 3 +- drivers/accel/ivpu/ivpu_sysfs.c | 5 +- 6 files changed, 121 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index f4171536640b..300eea8c305f 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -36,8 +36,6 @@ #define DRIVER_VERSION_STR "1.0.0 " UTS_RELEASE #endif -static struct lock_class_key submitted_jobs_xa_lock_class_key; - int ivpu_dbg_mask; module_param_named(dbg_mask, ivpu_dbg_mask, int, 0644); MODULE_PARM_DESC(dbg_mask, "Driver debug mask. See IVPU_DBG_* macros."); @@ -467,26 +465,6 @@ static const struct drm_driver driver = { .major = 1, }; -static void ivpu_context_abort_invalid(struct ivpu_device *vdev) -{ - struct ivpu_file_priv *file_priv; - unsigned long ctx_id; - - mutex_lock(&vdev->context_list_lock); - - xa_for_each(&vdev->context_xa, ctx_id, file_priv) { - if (!file_priv->has_mmu_faults || file_priv->aborted) - continue; - - mutex_lock(&file_priv->lock); - ivpu_context_abort_locked(file_priv); - file_priv->aborted = true; - mutex_unlock(&file_priv->lock); - } - - mutex_unlock(&vdev->context_list_lock); -} - static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg) { struct ivpu_device *vdev = arg; @@ -500,9 +478,6 @@ static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg) case IVPU_HW_IRQ_SRC_IPC: ivpu_ipc_irq_thread_handler(vdev); break; - case IVPU_HW_IRQ_SRC_MMU_EVTQ: - ivpu_context_abort_invalid(vdev); - break; case IVPU_HW_IRQ_SRC_DCT: ivpu_pm_dct_irq_thread_handler(vdev); break; @@ -619,16 +594,21 @@ static int ivpu_dev_init(struct ivpu_device *vdev) xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1); xa_init_flags(&vdev->db_xa, XA_FLAGS_ALLOC1); - lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key); INIT_LIST_HEAD(&vdev->bo_list); vdev->db_limit.min = IVPU_MIN_DB; vdev->db_limit.max = IVPU_MAX_DB; + INIT_WORK(&vdev->context_abort_work, ivpu_context_abort_thread_handler); + ret = drmm_mutex_init(&vdev->drm, &vdev->context_list_lock); if (ret) goto err_xa_destroy; + ret = drmm_mutex_init(&vdev->drm, &vdev->submitted_jobs_lock); + if (ret) + goto err_xa_destroy; + ret = drmm_mutex_init(&vdev->drm, &vdev->bo_list_lock); if (ret) goto err_xa_destroy; diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 3fdff3f6cffd..ebfcf3e42a3d 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -137,6 +137,7 @@ struct ivpu_device { struct mutex context_list_lock; /* Protects user context addition/removal */ struct xarray context_xa; struct xa_limit context_xa_limit; + struct work_struct context_abort_work; struct xarray db_xa; struct xa_limit db_limit; @@ -145,6 +146,7 @@ struct ivpu_device { struct mutex bo_list_lock; /* Protects bo_list */ struct list_head bo_list; + struct mutex submitted_jobs_lock; /* Protects submitted_jobs */ struct xarray submitted_jobs_xa; struct ivpu_ipc_consumer job_done_consumer; diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index 43507d3aea51..7fed3c8406ee 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -122,6 +122,7 @@ static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 p cmdq->priority = priority; cmdq->is_legacy = is_legacy; + cmdq->is_valid = true; ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &cmdq->id, cmdq, file_priv->cmdq_limit, &file_priv->cmdq_id_next, GFP_KERNEL); @@ -130,6 +131,7 @@ static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 p goto err_free_cmdq; } + ivpu_dbg(vdev, JOB, "Command queue %d created, ctx %d\n", cmdq->id, file_priv->ctx.id); return cmdq; err_free_cmdq: @@ -247,7 +249,8 @@ static int ivpu_cmdq_unregister(struct ivpu_file_priv *file_priv, struct ivpu_cm if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id); if (!ret) - ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->id); + ivpu_dbg(vdev, JOB, "Command queue %d destroyed, ctx %d\n", + cmdq->id, file_priv->ctx.id); } ret = ivpu_jsm_unregister_db(vdev, cmdq->db_id); @@ -303,8 +306,8 @@ static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u32 lockdep_assert_held(&file_priv->lock); cmdq = xa_load(&file_priv->cmdq_xa, cmdq_id); - if (!cmdq) { - ivpu_err(vdev, "Failed to find command queue with ID: %u\n", cmdq_id); + if (!cmdq || !cmdq->is_valid) { + ivpu_warn_ratelimited(vdev, "Failed to find command queue with ID: %u\n", cmdq_id); return NULL; } @@ -356,25 +359,21 @@ void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev) mutex_unlock(&vdev->context_list_lock); } -static void ivpu_cmdq_unregister_all(struct ivpu_file_priv *file_priv) -{ - struct ivpu_cmdq *cmdq; - unsigned long cmdq_id; - - xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) - ivpu_cmdq_unregister(file_priv, cmdq); -} - void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) { struct ivpu_device *vdev = file_priv->vdev; + struct ivpu_cmdq *cmdq; + unsigned long cmdq_id; lockdep_assert_held(&file_priv->lock); - ivpu_cmdq_unregister_all(file_priv); + xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) + ivpu_cmdq_unregister(file_priv, cmdq); if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS) ivpu_jsm_context_release(vdev, file_priv->ctx.id); + + file_priv->aborted = true; } static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job) @@ -513,16 +512,14 @@ static struct ivpu_job *ivpu_job_remove_from_submitted_jobs(struct ivpu_device * { struct ivpu_job *job; - xa_lock(&vdev->submitted_jobs_xa); - job = __xa_erase(&vdev->submitted_jobs_xa, job_id); + lockdep_assert_held(&vdev->submitted_jobs_lock); + job = xa_erase(&vdev->submitted_jobs_xa, job_id); if (xa_empty(&vdev->submitted_jobs_xa) && job) { vdev->busy_time = ktime_add(ktime_sub(ktime_get(), vdev->busy_start_ts), vdev->busy_time); } - xa_unlock(&vdev->submitted_jobs_xa); - return job; } @@ -530,6 +527,8 @@ static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32 { struct ivpu_job *job; + lockdep_assert_held(&vdev->submitted_jobs_lock); + job = ivpu_job_remove_from_submitted_jobs(vdev, job_id); if (!job) return -ENOENT; @@ -548,6 +547,10 @@ static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32 ivpu_stop_job_timeout_detection(vdev); ivpu_rpm_put(vdev); + + if (!xa_empty(&vdev->submitted_jobs_xa)) + ivpu_start_job_timeout_detection(vdev); + return 0; } @@ -556,8 +559,26 @@ void ivpu_jobs_abort_all(struct ivpu_device *vdev) struct ivpu_job *job; unsigned long id; + mutex_lock(&vdev->submitted_jobs_lock); + xa_for_each(&vdev->submitted_jobs_xa, id, job) ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED); + + mutex_unlock(&vdev->submitted_jobs_lock); +} + +void ivpu_cmdq_abort_all_jobs(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id) +{ + struct ivpu_job *job; + unsigned long id; + + mutex_lock(&vdev->submitted_jobs_lock); + + xa_for_each(&vdev->submitted_jobs_xa, id, job) + if (job->file_priv->ctx.id == ctx_id && job->cmdq_id == cmdq_id) + ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED); + + mutex_unlock(&vdev->submitted_jobs_lock); } static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) @@ -590,15 +611,18 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) goto err_unlock_file_priv; } - xa_lock(&vdev->submitted_jobs_xa); + job->cmdq_id = cmdq->id; + + mutex_lock(&vdev->submitted_jobs_lock); + is_first_job = xa_empty(&vdev->submitted_jobs_xa); - ret = __xa_alloc_cyclic(&vdev->submitted_jobs_xa, &job->job_id, job, file_priv->job_limit, - &file_priv->job_id_next, GFP_KERNEL); + ret = xa_alloc_cyclic(&vdev->submitted_jobs_xa, &job->job_id, job, file_priv->job_limit, + &file_priv->job_id_next, GFP_KERNEL); if (ret < 0) { ivpu_dbg(vdev, JOB, "Too many active jobs in ctx %d\n", file_priv->ctx.id); ret = -EBUSY; - goto err_unlock_submitted_jobs_xa; + goto err_unlock_submitted_jobs; } ret = ivpu_cmdq_push_job(cmdq, job); @@ -621,19 +645,21 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) job->job_id, file_priv->ctx.id, job->engine_idx, cmdq->priority, job->cmd_buf_vpu_addr, cmdq->jobq->header.tail); - xa_unlock(&vdev->submitted_jobs_xa); - + mutex_unlock(&vdev->submitted_jobs_lock); mutex_unlock(&file_priv->lock); - if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_HW)) + if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_HW)) { + mutex_lock(&vdev->submitted_jobs_lock); ivpu_job_signal_and_destroy(vdev, job->job_id, VPU_JSM_STATUS_SUCCESS); + mutex_unlock(&vdev->submitted_jobs_lock); + } return 0; err_erase_xa: - __xa_erase(&vdev->submitted_jobs_xa, job->job_id); -err_unlock_submitted_jobs_xa: - xa_unlock(&vdev->submitted_jobs_xa); + xa_erase(&vdev->submitted_jobs_xa, job->job_id); +err_unlock_submitted_jobs: + mutex_unlock(&vdev->submitted_jobs_lock); err_unlock_file_priv: mutex_unlock(&file_priv->lock); ivpu_rpm_put(vdev); @@ -843,19 +869,33 @@ int ivpu_cmdq_create_ioctl(struct drm_device *dev, void *data, struct drm_file * int ivpu_cmdq_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct ivpu_file_priv *file_priv = file->driver_priv; + struct ivpu_device *vdev = file_priv->vdev; struct drm_ivpu_cmdq_destroy *args = data; struct ivpu_cmdq *cmdq; + u32 cmdq_id; int ret = 0; mutex_lock(&file_priv->lock); cmdq = xa_load(&file_priv->cmdq_xa, args->cmdq_id); - if (!cmdq || cmdq->is_legacy) { + if (!cmdq || !cmdq->is_valid || cmdq->is_legacy) { ret = -ENOENT; goto unlock; } + /* + * There is no way to stop executing jobs per command queue + * in OS scheduling mode, mark command queue as invalid instead + * and it will be freed together with context release. + */ + if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS) { + cmdq->is_valid = false; + goto unlock; + } + + cmdq_id = cmdq->id; ivpu_cmdq_destroy(file_priv, cmdq); + ivpu_cmdq_abort_all_jobs(vdev, file_priv->ctx.id, cmdq_id); unlock: mutex_unlock(&file_priv->lock); return ret; @@ -866,7 +906,6 @@ ivpu_job_done_callback(struct ivpu_device *vdev, struct ivpu_ipc_hdr *ipc_hdr, struct vpu_jsm_msg *jsm_msg) { struct vpu_ipc_msg_payload_job_done *payload; - int ret; if (!jsm_msg) { ivpu_err(vdev, "IPC message has no JSM payload\n"); @@ -879,9 +918,10 @@ ivpu_job_done_callback(struct ivpu_device *vdev, struct ivpu_ipc_hdr *ipc_hdr, } payload = (struct vpu_ipc_msg_payload_job_done *)&jsm_msg->payload; - ret = ivpu_job_signal_and_destroy(vdev, payload->job_id, payload->job_status); - if (!ret && !xa_empty(&vdev->submitted_jobs_xa)) - ivpu_start_job_timeout_detection(vdev); + + mutex_lock(&vdev->submitted_jobs_lock); + ivpu_job_signal_and_destroy(vdev, payload->job_id, payload->job_status); + mutex_unlock(&vdev->submitted_jobs_lock); } void ivpu_job_done_consumer_init(struct ivpu_device *vdev) @@ -894,3 +934,36 @@ void ivpu_job_done_consumer_fini(struct ivpu_device *vdev) { ivpu_ipc_consumer_del(vdev, &vdev->job_done_consumer); } + +void ivpu_context_abort_thread_handler(struct work_struct *work) +{ + struct ivpu_device *vdev = container_of(work, struct ivpu_device, context_abort_work); + struct ivpu_file_priv *file_priv; + unsigned long ctx_id; + struct ivpu_job *job; + unsigned long id; + + mutex_lock(&vdev->context_list_lock); + xa_for_each(&vdev->context_xa, ctx_id, file_priv) { + if (!file_priv->has_mmu_faults || file_priv->aborted) + continue; + + mutex_lock(&file_priv->lock); + ivpu_context_abort_locked(file_priv); + mutex_unlock(&file_priv->lock); + } + mutex_unlock(&vdev->context_list_lock); + + if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW) + return; + /* + * In hardware scheduling mode NPU already has stopped processing jobs + * and won't send us any further notifications, thus we have to free job related resources + * and notify userspace + */ + mutex_lock(&vdev->submitted_jobs_lock); + xa_for_each(&vdev->submitted_jobs_xa, id, job) + if (job->file_priv->aborted) + ivpu_job_signal_and_destroy(vdev, job->job_id, DRM_IVPU_JOB_STATUS_ABORTED); + mutex_unlock(&vdev->submitted_jobs_lock); +} diff --git a/drivers/accel/ivpu/ivpu_job.h b/drivers/accel/ivpu/ivpu_job.h index 4d31277bcc41..fef8aed1fc88 100644 --- a/drivers/accel/ivpu/ivpu_job.h +++ b/drivers/accel/ivpu/ivpu_job.h @@ -31,6 +31,7 @@ struct ivpu_cmdq { u32 id; u32 db_id; u8 priority; + bool is_valid; bool is_legacy; }; @@ -51,6 +52,7 @@ struct ivpu_job { struct ivpu_file_priv *file_priv; struct dma_fence *done_fence; u64 cmd_buf_vpu_addr; + u32 cmdq_id; u32 job_id; u32 engine_idx; size_t bo_count; @@ -66,9 +68,11 @@ void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv); void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv); void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev); +void ivpu_cmdq_abort_all_jobs(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id); void ivpu_job_done_consumer_init(struct ivpu_device *vdev); void ivpu_job_done_consumer_fini(struct ivpu_device *vdev); +void ivpu_context_abort_thread_handler(struct work_struct *work); void ivpu_jobs_abort_all(struct ivpu_device *vdev); diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index 26ef52fbb93e..21f820dd0c65 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -890,8 +890,7 @@ void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons); } - if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_MMU_EVTQ)) - ivpu_err_ratelimited(vdev, "IRQ FIFO full\n"); + queue_work(system_wq, &vdev->context_abort_work); } void ivpu_mmu_evtq_dump(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_sysfs.c b/drivers/accel/ivpu/ivpu_sysfs.c index 616477fc17fa..8a616791c32f 100644 --- a/drivers/accel/ivpu/ivpu_sysfs.c +++ b/drivers/accel/ivpu/ivpu_sysfs.c @@ -30,11 +30,12 @@ npu_busy_time_us_show(struct device *dev, struct device_attribute *attr, char *b struct ivpu_device *vdev = to_ivpu_device(drm); ktime_t total, now = 0; - xa_lock(&vdev->submitted_jobs_xa); + mutex_lock(&vdev->submitted_jobs_lock); + total = vdev->busy_time; if (!xa_empty(&vdev->submitted_jobs_xa)) now = ktime_sub(ktime_get(), vdev->busy_start_ts); - xa_unlock(&vdev->submitted_jobs_xa); + mutex_unlock(&vdev->submitted_jobs_lock); return sysfs_emit(buf, "%lld\n", ktime_to_us(ktime_add(total, now))); } -- cgit v1.2.3-59-g8ed1b From 7bfc9fa99580b9b94da1c4cdcdebe3f792c1fe40 Mon Sep 17 00:00:00 2001 From: Maciej Falkowski Date: Tue, 7 Jan 2025 18:32:27 +0100 Subject: accel/ivpu: Expose NPU memory utilization info in sysfs Expose NPU memory utilization info in sysfs in bytes to show total memory used by NPU (FW + runtime). Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-5-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_sysfs.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_sysfs.c b/drivers/accel/ivpu/ivpu_sysfs.c index 8a616791c32f..97102feaf8dd 100644 --- a/drivers/accel/ivpu/ivpu_sysfs.c +++ b/drivers/accel/ivpu/ivpu_sysfs.c @@ -7,11 +7,14 @@ #include #include "ivpu_drv.h" +#include "ivpu_gem.h" #include "ivpu_fw.h" #include "ivpu_hw.h" #include "ivpu_sysfs.h" -/* +/** + * DOC: npu_busy_time_us + * * npu_busy_time_us is the time that the device spent executing jobs. * The time is counted when and only when there are jobs submitted to firmware. * @@ -42,6 +45,30 @@ npu_busy_time_us_show(struct device *dev, struct device_attribute *attr, char *b static DEVICE_ATTR_RO(npu_busy_time_us); +/** + * DOC: npu_memory_utilization + * + * The npu_memory_utilization is used to report in bytes a current NPU memory utilization. + * + */ +static ssize_t +npu_memory_utilization_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct drm_device *drm = dev_get_drvdata(dev); + struct ivpu_device *vdev = to_ivpu_device(drm); + struct ivpu_bo *bo; + u64 total_npu_memory = 0; + + mutex_lock(&vdev->bo_list_lock); + list_for_each_entry(bo, &vdev->bo_list, bo_list_node) + total_npu_memory += bo->base.base.size; + mutex_unlock(&vdev->bo_list_lock); + + return sysfs_emit(buf, "%lld\n", total_npu_memory); +} + +static DEVICE_ATTR_RO(npu_memory_utilization); + /** * DOC: sched_mode * @@ -65,6 +92,7 @@ static DEVICE_ATTR_RO(sched_mode); static struct attribute *ivpu_dev_attrs[] = { &dev_attr_npu_busy_time_us.attr, + &dev_attr_npu_memory_utilization.attr, &dev_attr_sched_mode.attr, NULL, }; -- cgit v1.2.3-59-g8ed1b From bc3e5f48b7ee021371dc37297678f7089be6ce28 Mon Sep 17 00:00:00 2001 From: Maciej Falkowski Date: Tue, 7 Jan 2025 18:32:28 +0100 Subject: accel/ivpu: Use workqueue for IRQ handling Convert IRQ bottom half from the thread handler into workqueue. This increases a stability in rare scenarios where driver on debugging/hardening kernels processes IRQ too slow and misses some interrupts due to it. Workqueue handler also gives a very minor performance increase. Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-6-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 39 ++++++++++----------------------------- drivers/accel/ivpu/ivpu_drv.h | 5 ++++- drivers/accel/ivpu/ivpu_hw.c | 5 ----- drivers/accel/ivpu/ivpu_hw.h | 9 --------- drivers/accel/ivpu/ivpu_hw_btrs.c | 3 +-- drivers/accel/ivpu/ivpu_ipc.c | 7 +++---- drivers/accel/ivpu/ivpu_ipc.h | 2 +- drivers/accel/ivpu/ivpu_job.c | 2 +- drivers/accel/ivpu/ivpu_job.h | 2 +- drivers/accel/ivpu/ivpu_pm.c | 3 ++- drivers/accel/ivpu/ivpu_pm.h | 2 +- 11 files changed, 24 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 300eea8c305f..9b0d99873fb3 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -421,6 +422,9 @@ void ivpu_prepare_for_reset(struct ivpu_device *vdev) { ivpu_hw_irq_disable(vdev); disable_irq(vdev->irq); + cancel_work_sync(&vdev->irq_ipc_work); + cancel_work_sync(&vdev->irq_dct_work); + cancel_work_sync(&vdev->context_abort_work); ivpu_ipc_disable(vdev); ivpu_mmu_disable(vdev); } @@ -465,31 +469,6 @@ static const struct drm_driver driver = { .major = 1, }; -static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg) -{ - struct ivpu_device *vdev = arg; - u8 irq_src; - - if (kfifo_is_empty(&vdev->hw->irq.fifo)) - return IRQ_NONE; - - while (kfifo_get(&vdev->hw->irq.fifo, &irq_src)) { - switch (irq_src) { - case IVPU_HW_IRQ_SRC_IPC: - ivpu_ipc_irq_thread_handler(vdev); - break; - case IVPU_HW_IRQ_SRC_DCT: - ivpu_pm_dct_irq_thread_handler(vdev); - break; - default: - ivpu_err_ratelimited(vdev, "Unknown IRQ source: %u\n", irq_src); - break; - } - } - - return IRQ_HANDLED; -} - static int ivpu_irq_init(struct ivpu_device *vdev) { struct pci_dev *pdev = to_pci_dev(vdev->drm.dev); @@ -501,12 +480,16 @@ static int ivpu_irq_init(struct ivpu_device *vdev) return ret; } + INIT_WORK(&vdev->irq_ipc_work, ivpu_ipc_irq_work_fn); + INIT_WORK(&vdev->irq_dct_work, ivpu_pm_irq_dct_work_fn); + INIT_WORK(&vdev->context_abort_work, ivpu_context_abort_work_fn); + ivpu_irq_handlers_init(vdev); vdev->irq = pci_irq_vector(pdev, 0); - ret = devm_request_threaded_irq(vdev->drm.dev, vdev->irq, ivpu_hw_irq_handler, - ivpu_irq_thread_handler, IRQF_NO_AUTOEN, DRIVER_NAME, vdev); + ret = devm_request_irq(vdev->drm.dev, vdev->irq, ivpu_hw_irq_handler, + IRQF_NO_AUTOEN, DRIVER_NAME, vdev); if (ret) ivpu_err(vdev, "Failed to request an IRQ %d\n", ret); @@ -599,8 +582,6 @@ static int ivpu_dev_init(struct ivpu_device *vdev) vdev->db_limit.min = IVPU_MIN_DB; vdev->db_limit.max = IVPU_MAX_DB; - INIT_WORK(&vdev->context_abort_work, ivpu_context_abort_thread_handler); - ret = drmm_mutex_init(&vdev->drm, &vdev->context_list_lock); if (ret) goto err_xa_destroy; diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index ebfcf3e42a3d..b57d878f2fcd 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -137,12 +137,15 @@ struct ivpu_device { struct mutex context_list_lock; /* Protects user context addition/removal */ struct xarray context_xa; struct xa_limit context_xa_limit; - struct work_struct context_abort_work; struct xarray db_xa; struct xa_limit db_limit; u32 db_next; + struct work_struct irq_ipc_work; + struct work_struct irq_dct_work; + struct work_struct context_abort_work; + struct mutex bo_list_lock; /* Protects bo_list */ struct list_head bo_list; diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index 4e1054f3466e..1b691375ee4d 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -285,8 +285,6 @@ void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable) void ivpu_irq_handlers_init(struct ivpu_device *vdev) { - INIT_KFIFO(vdev->hw->irq.fifo); - if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_37xx; else @@ -300,7 +298,6 @@ void ivpu_irq_handlers_init(struct ivpu_device *vdev) void ivpu_hw_irq_enable(struct ivpu_device *vdev) { - kfifo_reset(&vdev->hw->irq.fifo); ivpu_hw_ip_irq_enable(vdev); ivpu_hw_btrs_irq_enable(vdev); } @@ -327,8 +324,6 @@ irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr) /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ ivpu_hw_btrs_global_int_enable(vdev); - if (!kfifo_is_empty(&vdev->hw->irq.fifo)) - return IRQ_WAKE_THREAD; if (ip_handled || btrs_handled) return IRQ_HANDLED; return IRQ_NONE; diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h index fc4dbfc980c8..fbef9816b9d0 100644 --- a/drivers/accel/ivpu/ivpu_hw.h +++ b/drivers/accel/ivpu/ivpu_hw.h @@ -6,18 +6,10 @@ #ifndef __IVPU_HW_H__ #define __IVPU_HW_H__ -#include - #include "ivpu_drv.h" #include "ivpu_hw_btrs.h" #include "ivpu_hw_ip.h" -#define IVPU_HW_IRQ_FIFO_LENGTH 1024 - -#define IVPU_HW_IRQ_SRC_IPC 1 -#define IVPU_HW_IRQ_SRC_MMU_EVTQ 2 -#define IVPU_HW_IRQ_SRC_DCT 3 - struct ivpu_addr_range { resource_size_t start; resource_size_t end; @@ -27,7 +19,6 @@ struct ivpu_hw_info { struct { bool (*btrs_irq_handler)(struct ivpu_device *vdev, int irq); bool (*ip_irq_handler)(struct ivpu_device *vdev, int irq); - DECLARE_KFIFO(fifo, u8, IVPU_HW_IRQ_FIFO_LENGTH); } irq; struct { struct ivpu_addr_range global; diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c index 3212c99f3682..3753b00ed2d6 100644 --- a/drivers/accel/ivpu/ivpu_hw_btrs.c +++ b/drivers/accel/ivpu/ivpu_hw_btrs.c @@ -630,8 +630,7 @@ bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq) if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status)) { ivpu_dbg(vdev, IRQ, "Survivability IRQ\n"); - if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_DCT)) - ivpu_err_ratelimited(vdev, "IRQ FIFO full\n"); + queue_work(system_wq, &vdev->irq_dct_work); } if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status)) diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index 01ebf88fe6ef..0e096fd9b95d 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -459,13 +459,12 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev) } } - if (!list_empty(&ipc->cb_msg_list)) - if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_IPC)) - ivpu_err_ratelimited(vdev, "IRQ FIFO full\n"); + queue_work(system_wq, &vdev->irq_ipc_work); } -void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev) +void ivpu_ipc_irq_work_fn(struct work_struct *work) { + struct ivpu_device *vdev = container_of(work, struct ivpu_device, irq_ipc_work); struct ivpu_ipc_info *ipc = vdev->ipc; struct ivpu_ipc_rx_msg *rx_msg, *r; struct list_head cb_msg_list; diff --git a/drivers/accel/ivpu/ivpu_ipc.h b/drivers/accel/ivpu/ivpu_ipc.h index b4dfb504679b..b524a1985b9d 100644 --- a/drivers/accel/ivpu/ivpu_ipc.h +++ b/drivers/accel/ivpu/ivpu_ipc.h @@ -90,7 +90,7 @@ void ivpu_ipc_disable(struct ivpu_device *vdev); void ivpu_ipc_reset(struct ivpu_device *vdev); void ivpu_ipc_irq_handler(struct ivpu_device *vdev); -void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev); +void ivpu_ipc_irq_work_fn(struct work_struct *work); void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, u32 channel, ivpu_ipc_rx_callback_t callback); diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index 7fed3c8406ee..c678dcddb8d8 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -935,7 +935,7 @@ void ivpu_job_done_consumer_fini(struct ivpu_device *vdev) ivpu_ipc_consumer_del(vdev, &vdev->job_done_consumer); } -void ivpu_context_abort_thread_handler(struct work_struct *work) +void ivpu_context_abort_work_fn(struct work_struct *work) { struct ivpu_device *vdev = container_of(work, struct ivpu_device, context_abort_work); struct ivpu_file_priv *file_priv; diff --git a/drivers/accel/ivpu/ivpu_job.h b/drivers/accel/ivpu/ivpu_job.h index fef8aed1fc88..ff77ee1fcee2 100644 --- a/drivers/accel/ivpu/ivpu_job.h +++ b/drivers/accel/ivpu/ivpu_job.h @@ -72,7 +72,7 @@ void ivpu_cmdq_abort_all_jobs(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id) void ivpu_job_done_consumer_init(struct ivpu_device *vdev); void ivpu_job_done_consumer_fini(struct ivpu_device *vdev); -void ivpu_context_abort_thread_handler(struct work_struct *work); +void ivpu_context_abort_work_fn(struct work_struct *work); void ivpu_jobs_abort_all(struct ivpu_device *vdev); diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 6821051dfa3a..f41b3bfe40af 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -452,8 +452,9 @@ int ivpu_pm_dct_disable(struct ivpu_device *vdev) return 0; } -void ivpu_pm_dct_irq_thread_handler(struct ivpu_device *vdev) +void ivpu_pm_irq_dct_work_fn(struct work_struct *work) { + struct ivpu_device *vdev = container_of(work, struct ivpu_device, irq_dct_work); bool enable; int ret; diff --git a/drivers/accel/ivpu/ivpu_pm.h b/drivers/accel/ivpu/ivpu_pm.h index b70efe6c36e4..89b264cc0e3e 100644 --- a/drivers/accel/ivpu/ivpu_pm.h +++ b/drivers/accel/ivpu/ivpu_pm.h @@ -45,6 +45,6 @@ void ivpu_stop_job_timeout_detection(struct ivpu_device *vdev); int ivpu_pm_dct_init(struct ivpu_device *vdev); int ivpu_pm_dct_enable(struct ivpu_device *vdev, u8 active_percent); int ivpu_pm_dct_disable(struct ivpu_device *vdev); -void ivpu_pm_dct_irq_thread_handler(struct ivpu_device *vdev); +void ivpu_pm_irq_dct_work_fn(struct work_struct *work); #endif /* __IVPU_PM_H__ */ -- cgit v1.2.3-59-g8ed1b From 0240fa18d247c99a1967f2fed025296a89a1c5f5 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:29 +0100 Subject: accel/ivpu: Dump only first MMU fault from single context Stop dumping consecutive faults from an already faulty context immediately, instead of waiting for the context abort thread handler (IRQ handler bottom half) to abort currently executing jobs. Remove 'R' (record events) bit from context descriptor of a faulty context to prevent future faults generation. This change speeds up the IRQ handler by eliminating the need to print the fault content repeatedly. Additionally, it prevents flooding dmesg with errors, which was occurring due to the delay in the bottom half of the handler stopping fault-generating jobs. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-7-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_mmu.c | 51 +++++++++++++++++++++++++++++++---- drivers/accel/ivpu/ivpu_mmu_context.c | 13 --------- drivers/accel/ivpu/ivpu_mmu_context.h | 2 -- 3 files changed, 46 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index 21f820dd0c65..5ee4df892b3e 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -870,23 +870,64 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) return evt; } +static int ivpu_mmu_disable_events(struct ivpu_device *vdev, u32 ssid) +{ + struct ivpu_mmu_info *mmu = vdev->mmu; + struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; + u64 *entry; + u64 val; + + if (ssid > IVPU_MMU_CDTAB_ENT_COUNT) + return -EINVAL; + + entry = cdtab->base + (ssid * IVPU_MMU_CDTAB_ENT_SIZE); + + val = READ_ONCE(entry[0]); + val &= ~IVPU_MMU_CD_0_R; + WRITE_ONCE(entry[0], val); + + if (!ivpu_is_force_snoop_enabled(vdev)) + clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE); + + ivpu_mmu_cmdq_write_cfgi_all(vdev); + + return 0; +} + void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) { + struct ivpu_file_priv *file_priv; + u32 last_ssid = -1; u32 *event; u32 ssid; ivpu_dbg(vdev, IRQ, "MMU event queue\n"); - while ((event = ivpu_mmu_get_event(vdev)) != NULL) { - ivpu_mmu_dump_event(vdev, event); - + while ((event = ivpu_mmu_get_event(vdev))) { ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]); + + if (ssid == last_ssid) + continue; + + xa_lock(&vdev->context_xa); + file_priv = xa_load(&vdev->context_xa, ssid); + if (file_priv) { + if (file_priv->has_mmu_faults) { + event = NULL; + } else { + ivpu_mmu_disable_events(vdev, ssid); + file_priv->has_mmu_faults = true; + } + } + xa_unlock(&vdev->context_xa); + + if (event) + ivpu_mmu_dump_event(vdev, event); + if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) { ivpu_pm_trigger_recovery(vdev, "MMU event"); return; } - - ivpu_mmu_user_context_mark_invalid(vdev, ssid); REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons); } diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c index 891967a95bc3..d373443bbc83 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.c +++ b/drivers/accel/ivpu/ivpu_mmu_context.c @@ -631,16 +631,3 @@ void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev) ivpu_mmu_cd_clear(vdev, vdev->rctx.id); ivpu_mmu_context_fini(vdev, &vdev->rctx); } - -void ivpu_mmu_user_context_mark_invalid(struct ivpu_device *vdev, u32 ssid) -{ - struct ivpu_file_priv *file_priv; - - xa_lock(&vdev->context_xa); - - file_priv = xa_load(&vdev->context_xa, ssid); - if (file_priv) - file_priv->has_mmu_faults = true; - - xa_unlock(&vdev->context_xa); -} diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h index 8042fc067062..f255310968cf 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.h +++ b/drivers/accel/ivpu/ivpu_mmu_context.h @@ -37,8 +37,6 @@ void ivpu_mmu_global_context_fini(struct ivpu_device *vdev); int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev); void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev); -void ivpu_mmu_user_context_mark_invalid(struct ivpu_device *vdev, u32 ssid); - int ivpu_mmu_context_insert_node(struct ivpu_mmu_context *ctx, const struct ivpu_addr_range *range, u64 size, struct drm_mm_node *node); void ivpu_mmu_context_remove_node(struct ivpu_mmu_context *ctx, struct drm_mm_node *node); -- cgit v1.2.3-59-g8ed1b From 4480912f3f8b8a1fbb5ae12c5c547fd094ec4197 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:30 +0100 Subject: accel/ivpu: Move parts of MMU event IRQ handling to thread handler To prevent looping infinitely in MMU event handler we stop generating new events by removing 'R' (record) bit from context descriptor, but to ensure this change has effect KMD has to perform configuration invalidation followed by sync command. Because of that move parts of the interrupt handler that can take longer to a thread not to block in interrupt handler for too long. This includes: * disabling event queue for the time KMD updates MMU event queue consumer to ensure proper synchronization between MMU and KMD * removal of 'R' (record) bit from context descriptor to ensure no more faults are recorded until that context is destroyed Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-8-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_job.c | 7 +++- drivers/accel/ivpu/ivpu_mmu.c | 93 ++++++++++++++++++++++++++++--------------- drivers/accel/ivpu/ivpu_mmu.h | 2 + 3 files changed, 69 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index c678dcddb8d8..c55de9736d84 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -17,6 +17,7 @@ #include "ivpu_ipc.h" #include "ivpu_job.h" #include "ivpu_jsm_msg.h" +#include "ivpu_mmu.h" #include "ivpu_pm.h" #include "ivpu_trace.h" #include "vpu_boot_api.h" @@ -366,6 +367,7 @@ void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) unsigned long cmdq_id; lockdep_assert_held(&file_priv->lock); + ivpu_dbg(vdev, JOB, "Context ID: %u abort\n", file_priv->ctx.id); xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) ivpu_cmdq_unregister(file_priv, cmdq); @@ -373,6 +375,9 @@ void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS) ivpu_jsm_context_release(vdev, file_priv->ctx.id); + ivpu_mmu_disable_ssid_events(vdev, file_priv->ctx.id); + ivpu_mmu_discard_events(vdev); + file_priv->aborted = true; } @@ -939,8 +944,8 @@ void ivpu_context_abort_work_fn(struct work_struct *work) { struct ivpu_device *vdev = container_of(work, struct ivpu_device, context_abort_work); struct ivpu_file_priv *file_priv; - unsigned long ctx_id; struct ivpu_job *job; + unsigned long ctx_id; unsigned long id; mutex_lock(&vdev->context_list_lock); diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index 5ee4df892b3e..ae1dcd04051c 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -20,6 +20,12 @@ #define IVPU_MMU_REG_CR0 0x00200020u #define IVPU_MMU_REG_CR0ACK 0x00200024u #define IVPU_MMU_REG_CR0ACK_VAL_MASK GENMASK(31, 0) +#define IVPU_MMU_REG_CR0_ATSCHK_MASK BIT(4) +#define IVPU_MMU_REG_CR0_CMDQEN_MASK BIT(3) +#define IVPU_MMU_REG_CR0_EVTQEN_MASK BIT(2) +#define IVPU_MMU_REG_CR0_PRIQEN_MASK BIT(1) +#define IVPU_MMU_REG_CR0_SMMUEN_MASK BIT(0) + #define IVPU_MMU_REG_CR1 0x00200028u #define IVPU_MMU_REG_CR2 0x0020002cu #define IVPU_MMU_REG_IRQ_CTRL 0x00200050u @@ -141,12 +147,6 @@ #define IVPU_MMU_IRQ_EVTQ_EN BIT(2) #define IVPU_MMU_IRQ_GERROR_EN BIT(0) -#define IVPU_MMU_CR0_ATSCHK BIT(4) -#define IVPU_MMU_CR0_CMDQEN BIT(3) -#define IVPU_MMU_CR0_EVTQEN BIT(2) -#define IVPU_MMU_CR0_PRIQEN BIT(1) -#define IVPU_MMU_CR0_SMMUEN BIT(0) - #define IVPU_MMU_CR1_TABLE_SH GENMASK(11, 10) #define IVPU_MMU_CR1_TABLE_OC GENMASK(9, 8) #define IVPU_MMU_CR1_TABLE_IC GENMASK(7, 6) @@ -596,7 +596,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, 0); REGV_WR32(IVPU_MMU_REG_CMDQ_CONS, 0); - val = IVPU_MMU_CR0_CMDQEN; + val = REG_SET_FLD(IVPU_MMU_REG_CR0, CMDQEN, 0); ret = ivpu_mmu_reg_write_cr0(vdev, val); if (ret) return ret; @@ -617,12 +617,12 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) REGV_WR32(IVPU_MMU_REG_EVTQ_PROD_SEC, 0); REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, 0); - val |= IVPU_MMU_CR0_EVTQEN; + val = REG_SET_FLD(IVPU_MMU_REG_CR0, EVTQEN, val); ret = ivpu_mmu_reg_write_cr0(vdev, val); if (ret) return ret; - val |= IVPU_MMU_CR0_ATSCHK; + val = REG_SET_FLD(IVPU_MMU_REG_CR0, ATSCHK, val); ret = ivpu_mmu_reg_write_cr0(vdev, val); if (ret) return ret; @@ -631,7 +631,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) if (ret) return ret; - val |= IVPU_MMU_CR0_SMMUEN; + val = REG_SET_FLD(IVPU_MMU_REG_CR0, SMMUEN, val); return ivpu_mmu_reg_write_cr0(vdev, val); } @@ -870,7 +870,47 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) return evt; } -static int ivpu_mmu_disable_events(struct ivpu_device *vdev, u32 ssid) +static int ivpu_mmu_evtq_set(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(IVPU_MMU_REG_CR0); + + if (enable) + val = REG_SET_FLD(IVPU_MMU_REG_CR0, EVTQEN, val); + else + val = REG_CLR_FLD(IVPU_MMU_REG_CR0, EVTQEN, val); + REGV_WR32(IVPU_MMU_REG_CR0, val); + + return REGV_POLL_FLD(IVPU_MMU_REG_CR0ACK, VAL, val, IVPU_MMU_REG_TIMEOUT_US); +} + +static int ivpu_mmu_evtq_enable(struct ivpu_device *vdev) +{ + return ivpu_mmu_evtq_set(vdev, true); +} + +static int ivpu_mmu_evtq_disable(struct ivpu_device *vdev) +{ + return ivpu_mmu_evtq_set(vdev, false); +} + +void ivpu_mmu_discard_events(struct ivpu_device *vdev) +{ + /* + * Disable event queue (stop MMU from updating the producer) + * to allow synchronization of consumer and producer indexes + */ + ivpu_mmu_evtq_disable(vdev); + + vdev->mmu->evtq.cons = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC); + REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons); + vdev->mmu->evtq.prod = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC); + + ivpu_mmu_evtq_enable(vdev); + + drm_WARN_ON_ONCE(&vdev->drm, vdev->mmu->evtq.cons != vdev->mmu->evtq.prod); +} + +int ivpu_mmu_disable_ssid_events(struct ivpu_device *vdev, u32 ssid) { struct ivpu_mmu_info *mmu = vdev->mmu; struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; @@ -890,6 +930,7 @@ static int ivpu_mmu_disable_events(struct ivpu_device *vdev, u32 ssid) clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE); ivpu_mmu_cmdq_write_cfgi_all(vdev); + ivpu_mmu_cmdq_sync(vdev); return 0; } @@ -897,38 +938,26 @@ static int ivpu_mmu_disable_events(struct ivpu_device *vdev, u32 ssid) void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) { struct ivpu_file_priv *file_priv; - u32 last_ssid = -1; u32 *event; u32 ssid; ivpu_dbg(vdev, IRQ, "MMU event queue\n"); while ((event = ivpu_mmu_get_event(vdev))) { - ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]); - - if (ssid == last_ssid) - continue; + ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, *event); + if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) { + ivpu_mmu_dump_event(vdev, event); + ivpu_pm_trigger_recovery(vdev, "MMU event"); + return; + } - xa_lock(&vdev->context_xa); file_priv = xa_load(&vdev->context_xa, ssid); if (file_priv) { - if (file_priv->has_mmu_faults) { - event = NULL; - } else { - ivpu_mmu_disable_events(vdev, ssid); - file_priv->has_mmu_faults = true; + if (!READ_ONCE(file_priv->has_mmu_faults)) { + ivpu_mmu_dump_event(vdev, event); + WRITE_ONCE(file_priv->has_mmu_faults, true); } } - xa_unlock(&vdev->context_xa); - - if (event) - ivpu_mmu_dump_event(vdev, event); - - if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) { - ivpu_pm_trigger_recovery(vdev, "MMU event"); - return; - } - REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons); } queue_work(system_wq, &vdev->context_abort_work); diff --git a/drivers/accel/ivpu/ivpu_mmu.h b/drivers/accel/ivpu/ivpu_mmu.h index 7afea9cd8731..1ce7529746ad 100644 --- a/drivers/accel/ivpu/ivpu_mmu.h +++ b/drivers/accel/ivpu/ivpu_mmu.h @@ -47,5 +47,7 @@ int ivpu_mmu_invalidate_tlb(struct ivpu_device *vdev, u16 ssid); void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev); void ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev); void ivpu_mmu_evtq_dump(struct ivpu_device *vdev); +void ivpu_mmu_discard_events(struct ivpu_device *vdev); +int ivpu_mmu_disable_ssid_events(struct ivpu_device *vdev, u32 ssid); #endif /* __IVPU_MMU_H__ */ -- cgit v1.2.3-59-g8ed1b From 353b8f48390d36b39276ff6af61464ec64cd4d5c Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:31 +0100 Subject: accel/ivpu: Fix missing MMU events from reserved SSID Generate recovery when fault from reserved context is detected. Add Abort (A) bit to reserved (1) SSID to ensure NPU also receives a fault. There is no way to create a file_priv with reserved SSID but it is still possible to receive MMU faults from that SSID as it is a default NPU HW setting. Such situation will occur if FW freed context related resources but still performed access to DRAM. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-9-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_mmu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index ae1dcd04051c..b80bdded9fd7 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -725,8 +725,8 @@ static int ivpu_mmu_cdtab_entry_set(struct ivpu_device *vdev, u32 ssid, u64 cd_d cd[2] = 0; cd[3] = 0x0000000000007444; - /* For global context generate memory fault on VPU */ - if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) + /* For global and reserved contexts generate memory fault on VPU */ + if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID || ssid == IVPU_RESERVED_CONTEXT_MMU_SSID) cd[0] |= IVPU_MMU_CD_0_A; if (valid) @@ -945,7 +945,8 @@ void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) while ((event = ivpu_mmu_get_event(vdev))) { ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, *event); - if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) { + if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID || + ssid == IVPU_RESERVED_CONTEXT_MMU_SSID) { ivpu_mmu_dump_event(vdev, event); ivpu_pm_trigger_recovery(vdev, "MMU event"); return; -- cgit v1.2.3-59-g8ed1b From ae06e0b3bfe07321c6a865df1b701e64194ec66e Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:32 +0100 Subject: accel/ivpu: Set command queue management capability based on HWS Control explicit command queue management capability bit based on scheduling mode. Capability will be available only when hardware scheduling mode is set. There is no point of allowing user space to create and destroy command queues with OS schedling mode because FW does not support all required functionalities for correct command queue management with OS scheduling. Return -ENODEV from command queue create/destroy/submit IOCTLs. Remove is_valid field from struct ivpu_job_cmdq Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-10-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 19 +++++++------------ drivers/accel/ivpu/ivpu_drv.h | 1 + drivers/accel/ivpu/ivpu_job.c | 24 +++++++++++------------- drivers/accel/ivpu/ivpu_job.h | 1 - 4 files changed, 19 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 9b0d99873fb3..6a80d626d609 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -127,23 +127,18 @@ void ivpu_file_priv_put(struct ivpu_file_priv **link) kref_put(&file_priv->ref, file_priv_release); } -static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param *args) +bool ivpu_is_capable(struct ivpu_device *vdev, u32 capability) { - switch (args->index) { + switch (capability) { case DRM_IVPU_CAP_METRIC_STREAMER: - args->value = 1; - break; + return true; case DRM_IVPU_CAP_DMA_MEMORY_RANGE: - args->value = 1; - break; + return true; case DRM_IVPU_CAP_MANAGE_CMDQ: - args->value = 1; - break; + return vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW; default: - return -EINVAL; + return false; } - - return 0; } static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file) @@ -203,7 +198,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f args->value = vdev->hw->sku; break; case DRM_IVPU_PARAM_CAPABILITIES: - ret = ivpu_get_capabilities(vdev, args); + args->value = ivpu_is_capable(vdev, args->index); break; default: ret = -EINVAL; diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index b57d878f2fcd..d53902b34070 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -213,6 +213,7 @@ void ivpu_file_priv_put(struct ivpu_file_priv **link); int ivpu_boot(struct ivpu_device *vdev); int ivpu_shutdown(struct ivpu_device *vdev); void ivpu_prepare_for_reset(struct ivpu_device *vdev); +bool ivpu_is_capable(struct ivpu_device *vdev, u32 capability); static inline u8 ivpu_revision(struct ivpu_device *vdev) { diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index c55de9736d84..37ea92eb4b25 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -123,7 +123,6 @@ static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 p cmdq->priority = priority; cmdq->is_legacy = is_legacy; - cmdq->is_valid = true; ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &cmdq->id, cmdq, file_priv->cmdq_limit, &file_priv->cmdq_id_next, GFP_KERNEL); @@ -307,7 +306,7 @@ static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u32 lockdep_assert_held(&file_priv->lock); cmdq = xa_load(&file_priv->cmdq_xa, cmdq_id); - if (!cmdq || !cmdq->is_valid) { + if (!cmdq) { ivpu_warn_ratelimited(vdev, "Failed to find command queue with ID: %u\n", cmdq_id); return NULL; } @@ -832,6 +831,9 @@ int ivpu_cmdq_submit_ioctl(struct drm_device *dev, void *data, struct drm_file * struct ivpu_file_priv *file_priv = file->driver_priv; struct drm_ivpu_cmdq_submit *args = data; + if (!ivpu_is_capable(file_priv->vdev, DRM_IVPU_CAP_MANAGE_CMDQ)) + return -ENODEV; + if (args->cmdq_id < IVPU_CMDQ_MIN_ID || args->cmdq_id > IVPU_CMDQ_MAX_ID) return -EINVAL; @@ -857,6 +859,9 @@ int ivpu_cmdq_create_ioctl(struct drm_device *dev, void *data, struct drm_file * struct drm_ivpu_cmdq_create *args = data; struct ivpu_cmdq *cmdq; + if (!ivpu_is_capable(file_priv->vdev, DRM_IVPU_CAP_MANAGE_CMDQ)) + return -ENODEV; + if (args->priority > DRM_IVPU_JOB_PRIORITY_REALTIME) return -EINVAL; @@ -880,24 +885,17 @@ int ivpu_cmdq_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file u32 cmdq_id; int ret = 0; + if (!ivpu_is_capable(vdev, DRM_IVPU_CAP_MANAGE_CMDQ)) + return -ENODEV; + mutex_lock(&file_priv->lock); cmdq = xa_load(&file_priv->cmdq_xa, args->cmdq_id); - if (!cmdq || !cmdq->is_valid || cmdq->is_legacy) { + if (!cmdq || cmdq->is_legacy) { ret = -ENOENT; goto unlock; } - /* - * There is no way to stop executing jobs per command queue - * in OS scheduling mode, mark command queue as invalid instead - * and it will be freed together with context release. - */ - if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS) { - cmdq->is_valid = false; - goto unlock; - } - cmdq_id = cmdq->id; ivpu_cmdq_destroy(file_priv, cmdq); ivpu_cmdq_abort_all_jobs(vdev, file_priv->ctx.id, cmdq_id); diff --git a/drivers/accel/ivpu/ivpu_job.h b/drivers/accel/ivpu/ivpu_job.h index ff77ee1fcee2..2e301c2eea7b 100644 --- a/drivers/accel/ivpu/ivpu_job.h +++ b/drivers/accel/ivpu/ivpu_job.h @@ -31,7 +31,6 @@ struct ivpu_cmdq { u32 id; u32 db_id; u8 priority; - bool is_valid; bool is_legacy; }; -- cgit v1.2.3-59-g8ed1b From e52443608934952fc978234cf7d639d6aa3f1856 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:33 +0100 Subject: accel/ivpu: Fix locking order in ivpu_cmdq_destroy_ioctl Fix deadlock caused by inversed locking order in ivpu_job_submit() and ivpu_cmdq_destroy_ioctl(). Both functions operate locking file_priv->lock and submitted_jobs_lock. Unlock file_priv->lock in ivpu_cmdq_destroy_ioctl() before calling ivpu_cmdq_abort_all_jobs() function which locks submitted_jobs_lock. That way locking order is maintained: 1) global submitted_jobs_lock first 2) per context file_priv->lock second Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-11-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_job.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index 37ea92eb4b25..c694822a14bf 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -883,7 +883,7 @@ int ivpu_cmdq_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file struct drm_ivpu_cmdq_destroy *args = data; struct ivpu_cmdq *cmdq; u32 cmdq_id; - int ret = 0; + int ret; if (!ivpu_is_capable(vdev, DRM_IVPU_CAP_MANAGE_CMDQ)) return -ENODEV; @@ -893,13 +893,16 @@ int ivpu_cmdq_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file cmdq = xa_load(&file_priv->cmdq_xa, args->cmdq_id); if (!cmdq || cmdq->is_legacy) { ret = -ENOENT; - goto unlock; + goto err_unlock; } cmdq_id = cmdq->id; ivpu_cmdq_destroy(file_priv, cmdq); + mutex_unlock(&file_priv->lock); ivpu_cmdq_abort_all_jobs(vdev, file_priv->ctx.id, cmdq_id); -unlock: + return 0; + +err_unlock: mutex_unlock(&file_priv->lock); return ret; } -- cgit v1.2.3-59-g8ed1b From ab680dc6c78aa035e944ecc8c48a1caab9f39924 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:34 +0100 Subject: accel/ivpu: Fix locking order in ivpu_job_submit Fix deadlock in job submission and abort handling. When a thread aborts currently executing jobs due to a fault, it first locks the global lock protecting submitted_jobs (#1). After the last job is destroyed, it proceeds to release the related context and locks file_priv (#2). Meanwhile, in the job submission thread, the file_priv lock (#2) is taken first, and then the submitted_jobs lock (#1) is obtained when a job is added to the submitted jobs list. CPU0 CPU1 ---- ---- (for example due to a fault) (jobs submissions keep coming) lock(&vdev->submitted_jobs_lock) #1 ivpu_jobs_abort_all() job_destroy() lock(&file_priv->lock) #2 lock(&vdev->submitted_jobs_lock) #1 file_priv_release() lock(&vdev->context_list_lock) lock(&file_priv->lock) #2 This order of locking causes a deadlock. To resolve this issue, change the order of locking in ivpu_job_submit(). Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-12-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_job.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index c694822a14bf..c93ea37062d7 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -597,6 +597,7 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) if (ret < 0) return ret; + mutex_lock(&vdev->submitted_jobs_lock); mutex_lock(&file_priv->lock); if (cmdq_id == 0) @@ -606,19 +607,17 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) if (!cmdq) { ivpu_warn_ratelimited(vdev, "Failed to get job queue, ctx %d\n", file_priv->ctx.id); ret = -EINVAL; - goto err_unlock_file_priv; + goto err_unlock; } ret = ivpu_cmdq_register(file_priv, cmdq); if (ret) { ivpu_err(vdev, "Failed to register command queue: %d\n", ret); - goto err_unlock_file_priv; + goto err_unlock; } job->cmdq_id = cmdq->id; - mutex_lock(&vdev->submitted_jobs_lock); - is_first_job = xa_empty(&vdev->submitted_jobs_xa); ret = xa_alloc_cyclic(&vdev->submitted_jobs_xa, &job->job_id, job, file_priv->job_limit, &file_priv->job_id_next, GFP_KERNEL); @@ -626,7 +625,7 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) ivpu_dbg(vdev, JOB, "Too many active jobs in ctx %d\n", file_priv->ctx.id); ret = -EBUSY; - goto err_unlock_submitted_jobs; + goto err_unlock; } ret = ivpu_cmdq_push_job(cmdq, job); @@ -649,22 +648,20 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id) job->job_id, file_priv->ctx.id, job->engine_idx, cmdq->priority, job->cmd_buf_vpu_addr, cmdq->jobq->header.tail); - mutex_unlock(&vdev->submitted_jobs_lock); mutex_unlock(&file_priv->lock); if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_HW)) { - mutex_lock(&vdev->submitted_jobs_lock); ivpu_job_signal_and_destroy(vdev, job->job_id, VPU_JSM_STATUS_SUCCESS); - mutex_unlock(&vdev->submitted_jobs_lock); } + mutex_unlock(&vdev->submitted_jobs_lock); + return 0; err_erase_xa: xa_erase(&vdev->submitted_jobs_xa, job->job_id); -err_unlock_submitted_jobs: +err_unlock: mutex_unlock(&vdev->submitted_jobs_lock); -err_unlock_file_priv: mutex_unlock(&file_priv->lock); ivpu_rpm_put(vdev); return ret; -- cgit v1.2.3-59-g8ed1b From dad945c27a42dfadddff1049cf5ae417209a8996 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:35 +0100 Subject: accel/ivpu: Add handling of VPU_JSM_STATUS_MVNCI_CONTEXT_VIOLATION_HW Mark as invalid context of a job that returned HW context violation error and queue work that aborts jobs from faulty context. Add engine reset to the context abort thread handler to not only abort currently executing jobs but also to ensure NPU invalid state recovery. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-13-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_job.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index c93ea37062d7..3c162ac41a1d 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -533,6 +533,26 @@ static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32 lockdep_assert_held(&vdev->submitted_jobs_lock); + job = xa_load(&vdev->submitted_jobs_xa, job_id); + if (!job) + return -ENOENT; + + if (job_status == VPU_JSM_STATUS_MVNCI_CONTEXT_VIOLATION_HW) { + guard(mutex)(&job->file_priv->lock); + + if (job->file_priv->has_mmu_faults) + return 0; + + /* + * Mark context as faulty and defer destruction of the job to jobs abort thread + * handler to synchronize between both faults and jobs returning context violation + * status and ensure both are handled in the same way + */ + job->file_priv->has_mmu_faults = true; + queue_work(system_wq, &vdev->context_abort_work); + return 0; + } + job = ivpu_job_remove_from_submitted_jobs(vdev, job_id); if (!job) return -ENOENT; @@ -946,6 +966,9 @@ void ivpu_context_abort_work_fn(struct work_struct *work) unsigned long ctx_id; unsigned long id; + if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) + ivpu_jsm_reset_engine(vdev, 0); + mutex_lock(&vdev->context_list_lock); xa_for_each(&vdev->context_xa, ctx_id, file_priv) { if (!file_priv->has_mmu_faults || file_priv->aborted) @@ -959,6 +982,8 @@ void ivpu_context_abort_work_fn(struct work_struct *work) if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW) return; + + ivpu_jsm_hws_resume_engine(vdev, 0); /* * In hardware scheduling mode NPU already has stopped processing jobs * and won't send us any further notifications, thus we have to free job related resources -- cgit v1.2.3-59-g8ed1b From dd4f78ec6a6f82d02e59d6cadde6b92ed0507a4d Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 7 Jan 2025 18:32:36 +0100 Subject: accel/ivpu: Add platform detection for presilicon Use highest buttress VPU_STATUS register bits(15:13) that encode platform type as follows: 0 - Silicon 2 - Simics 3 - FPGA 4 - Hybrid SLE Remove old DMI based method. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jacek Lawrynowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-14-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.h | 4 ++- drivers/accel/ivpu/ivpu_hw.c | 41 +++++++++++++------------------ drivers/accel/ivpu/ivpu_hw_btrs.c | 7 ++++++ drivers/accel/ivpu/ivpu_hw_btrs.h | 1 + drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h | 1 + 5 files changed, 29 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index d53902b34070..ca21102ca366 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -58,6 +58,7 @@ #define IVPU_PLATFORM_SILICON 0 #define IVPU_PLATFORM_SIMICS 2 #define IVPU_PLATFORM_FPGA 3 +#define IVPU_PLATFORM_HSLE 4 #define IVPU_PLATFORM_INVALID 8 #define IVPU_SCHED_MODE_AUTO -1 @@ -288,7 +289,8 @@ static inline bool ivpu_is_simics(struct ivpu_device *vdev) static inline bool ivpu_is_fpga(struct ivpu_device *vdev) { - return ivpu_get_platform(vdev) == IVPU_PLATFORM_FPGA; + return ivpu_get_platform(vdev) == IVPU_PLATFORM_FPGA || + ivpu_get_platform(vdev) == IVPU_PLATFORM_HSLE; } static inline bool ivpu_is_force_snoop_enabled(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index 1b691375ee4d..e332f19ab51d 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -19,38 +19,31 @@ static char *platform_to_str(u32 platform) return "SIMICS"; case IVPU_PLATFORM_FPGA: return "FPGA"; + case IVPU_PLATFORM_HSLE: + return "HSLE"; default: return "Invalid platform"; } } -static const struct dmi_system_id dmi_platform_simulation[] = { - { - .ident = "Intel Simics", - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "lnlrvp"), - DMI_MATCH(DMI_BOARD_VERSION, "1.0"), - DMI_MATCH(DMI_BOARD_SERIAL, "123456789"), - }, - }, - { - .ident = "Intel Simics", - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "Simics"), - }, - }, - { } -}; - static void platform_init(struct ivpu_device *vdev) { - if (dmi_check_system(dmi_platform_simulation)) - vdev->platform = IVPU_PLATFORM_SIMICS; - else - vdev->platform = IVPU_PLATFORM_SILICON; + int platform = ivpu_hw_btrs_platform_read(vdev); + + ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n", platform_to_str(platform), platform); + + switch (platform) { + case IVPU_PLATFORM_SILICON: + case IVPU_PLATFORM_SIMICS: + case IVPU_PLATFORM_FPGA: + case IVPU_PLATFORM_HSLE: + vdev->platform = platform; + break; - ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n", - platform_to_str(vdev->platform), vdev->platform); + default: + ivpu_err(vdev, "Invalid platform type: %d\n", platform); + break; + } } static void wa_init(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c index 3753b00ed2d6..56c56012b980 100644 --- a/drivers/accel/ivpu/ivpu_hw_btrs.c +++ b/drivers/accel/ivpu/ivpu_hw_btrs.c @@ -887,3 +887,10 @@ void ivpu_hw_btrs_diagnose_failure(struct ivpu_device *vdev) else return diagnose_failure_lnl(vdev); } + +int ivpu_hw_btrs_platform_read(struct ivpu_device *vdev) +{ + u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS); + + return REG_GET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PLATFORM, reg); +} diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.h b/drivers/accel/ivpu/ivpu_hw_btrs.h index 04f14f50fed6..1fd71b4d4ab0 100644 --- a/drivers/accel/ivpu/ivpu_hw_btrs.h +++ b/drivers/accel/ivpu/ivpu_hw_btrs.h @@ -46,5 +46,6 @@ void ivpu_hw_btrs_global_int_disable(struct ivpu_device *vdev); void ivpu_hw_btrs_irq_enable(struct ivpu_device *vdev); void ivpu_hw_btrs_irq_disable(struct ivpu_device *vdev); void ivpu_hw_btrs_diagnose_failure(struct ivpu_device *vdev); +int ivpu_hw_btrs_platform_read(struct ivpu_device *vdev); #endif /* __IVPU_HW_BTRS_H__ */ diff --git a/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h b/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h index fc51f3098f97..fff2ef2cada6 100644 --- a/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h +++ b/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h @@ -86,6 +86,7 @@ #define VPU_HW_BTRS_LNL_VPU_STATUS_POWER_RESOURCE_OWN_ACK_MASK BIT_MASK(7) #define VPU_HW_BTRS_LNL_VPU_STATUS_PERF_CLK_MASK BIT_MASK(11) #define VPU_HW_BTRS_LNL_VPU_STATUS_DISABLE_CLK_RELINQUISH_MASK BIT_MASK(12) +#define VPU_HW_BTRS_LNL_VPU_STATUS_PLATFORM_MASK GENMASK(31, 29) #define VPU_HW_BTRS_LNL_IP_RESET 0x00000160u #define VPU_HW_BTRS_LNL_IP_RESET_TRIGGER_MASK BIT_MASK(0) -- cgit v1.2.3-59-g8ed1b From 74509d54ebf1ecfbdf5f7edec32c490fefa01b8b Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 7 Jan 2025 18:32:37 +0100 Subject: accel/ivpu: Enable HWS by default on all platforms Enable HWS on selected platforms if FW API version is above 3.19. Signed-off-by: Maciej Falkowski Reviewed-by: Karol Wachowski Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250107173238.381120-15-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_fw.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 6037ec0b3096..6cf1fb826d1b 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -145,7 +145,18 @@ ivpu_fw_sched_mode_select(struct ivpu_device *vdev, const struct vpu_firmware_he if (ivpu_sched_mode != IVPU_SCHED_MODE_AUTO) return ivpu_sched_mode; - return VPU_SCHEDULING_MODE_OS; + if (IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, JSM, 3, 24)) + return VPU_SCHEDULING_MODE_OS; + + switch (ivpu_device_id(vdev)) { + case PCI_DEVICE_ID_MTL: + case PCI_DEVICE_ID_ARL: + case PCI_DEVICE_ID_LNL: + case PCI_DEVICE_ID_PTL_P: + return VPU_SCHEDULING_MODE_HW; + default: + return VPU_SCHEDULING_MODE_OS; + } } static int ivpu_fw_parse(struct ivpu_device *vdev) -- cgit v1.2.3-59-g8ed1b From f7dfd3db3e0459765176124b4b7e4b4b93533676 Mon Sep 17 00:00:00 2001 From: Vivek Kasireddy Date: Wed, 11 Dec 2024 21:54:21 -0800 Subject: drm/virtio: Fix UAF in virtgpu_dma_buf_free_obj() Fix the following issues identified by Smatch static checker: - The call to dma_buf_put(attach->dmabuf) after dma_buf_detach() leads to a UAF bug as dma_buf_detach() frees the attach object. Fix this by extracting the dmabuf object from attach and using that in the call to dma_buf_put(). - The resv object is extracted from attach before checking to see if attach is valid (that is !NULL) or not. Although, attach would very likely be valid, fix this by making sure that the resv object is used only after ensuring that attach is valid. Fixes: 2885e575abc7 ("drm/virtio: Add helpers to initialize and free the imported object") Fixes: ca77f27a2665 ("drm/virtio: Import prime buffers from other devices as guest blobs") Cc: Gerd Hoffmann Cc: Dmitry Osipenko Cc: Gurchetan Singh Cc: Chia-I Wu Reported-by: Dan Carpenter Signed-off-by: Vivek Kasireddy Link: https://patchwork.freedesktop.org/patch/msgid/20241212055421.775759-1-vivek.kasireddy@intel.com Reviewed-by: Dmitry Osipenko Tested-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko [dmitry.osipenko@collabora.com: Edited commit title] --- drivers/gpu/drm/virtio/virtgpu_prime.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index b3664c12843d..f92133a01195 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -189,10 +189,11 @@ static void virtgpu_dma_buf_free_obj(struct drm_gem_object *obj) struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); struct virtio_gpu_device *vgdev = obj->dev->dev_private; struct dma_buf_attachment *attach = obj->import_attach; - struct dma_resv *resv = attach->dmabuf->resv; if (attach) { - dma_resv_lock(resv, NULL); + struct dma_buf *dmabuf = attach->dmabuf; + + dma_resv_lock(dmabuf->resv, NULL); virtio_gpu_detach_object_fenced(bo); @@ -200,10 +201,10 @@ static void virtgpu_dma_buf_free_obj(struct drm_gem_object *obj) dma_buf_unmap_attachment(attach, bo->sgt, DMA_BIDIRECTIONAL); - dma_resv_unlock(resv); + dma_resv_unlock(dmabuf->resv); - dma_buf_detach(attach->dmabuf, attach); - dma_buf_put(attach->dmabuf); + dma_buf_detach(dmabuf, attach); + dma_buf_put(dmabuf); } if (bo->created) { -- cgit v1.2.3-59-g8ed1b From 5dd8b536bbdaee00df1e8dbd8dc4e9fc2f7fadcb Mon Sep 17 00:00:00 2001 From: Vivek Kasireddy Date: Tue, 10 Dec 2024 22:43:43 -0800 Subject: drm/virtio: Lock the VGA resources during initialization If another driver for a VGA compatible GPU (that is passthrough'd) locks the VGA resources (by calling vga_get()), then virtio_gpu driver would encounter the following errors and fail to load during probe and initialization: Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1 virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22 This issue is only seen if virtio-gpu and the other GPU are on different PCI buses, which can happen if the user includes an additional PCIe port and associates the VGA compatible GPU with it while launching Qemu: qemu-system-x86_64... -device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true -device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on -device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ... In the above example, the device 03:00.0 is an Intel DG2 card and this issue is seen when both i915 driver and virtio_gpu driver are loading (or initializing) concurrently or when i915 is loaded first. Note that during initalization, i915 driver does the following in intel_vga_reset_io_mem(): vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); outb(inb(VGA_MIS_R), VGA_MIS_W); vga_put(pdev, VGA_RSRC_LEGACY_IO); Although, virtio-gpu might own the VGA resources initially, the above call (in i915) to vga_get_uninterruptible() would result in these resources being taken away, which means that virtio-gpu would not be able to decode VGA anymore. This happens in __vga_tryget() when it calls pci_set_vga_state(conflict->pdev, false, pci_bits, flags); where pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE Therefore, to solve this issue, virtio-gpu driver needs to call vga_get() whenever it needs to reclaim and access VGA resources, which is during initial probe and setup. After that, a call to vga_put() would release the lock to allow other VGA compatible devices to access these shared VGA resources. Cc: Gerd Hoffmann Cc: Gurchetan Singh Cc: Chia-I Wu Reported-by: Dmitry Osipenko Signed-off-by: Vivek Kasireddy Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com Tested-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko --- drivers/gpu/drm/virtio/virtgpu_drv.c | 40 +++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 6a67c6297d58..d4309dba557b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,8 @@ #include "virtgpu_drv.h" +#define PCI_DEVICE_ID_VIRTIO_GPU 0x1050 + static const struct drm_driver driver; static int virtio_gpu_modeset = -1; @@ -162,7 +165,42 @@ static struct virtio_driver virtio_gpu_driver = { .config_changed = virtio_gpu_config_changed }; -module_virtio_driver(virtio_gpu_driver); +static int __init virtio_gpu_driver_init(void) +{ + struct pci_dev *pdev; + int ret; + + pdev = pci_get_device(PCI_VENDOR_ID_REDHAT_QUMRANET, + PCI_DEVICE_ID_VIRTIO_GPU, + NULL); + if (!pdev) + return -ENODEV; + + if (pci_is_vga(pdev)) { + ret = vga_get_interruptible(pdev, + VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); + if (ret) + goto error; + } + + ret = register_virtio_driver(&virtio_gpu_driver); + + if (pci_is_vga(pdev)) + vga_put(pdev, VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); + +error: + pci_dev_put(pdev); + + return ret; +} + +static void __exit virtio_gpu_driver_exit(void) +{ + unregister_virtio_driver(&virtio_gpu_driver); +} + +module_init(virtio_gpu_driver_init); +module_exit(virtio_gpu_driver_exit); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION("Virtio GPU driver"); -- cgit v1.2.3-59-g8ed1b From ffda6454267d0b870f3a09945a7ce88137b914a6 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Fri, 29 Nov 2024 18:53:57 +0300 Subject: drm/virtio: Set missing bo->attached flag VirtIO-GPU driver now supports detachment of shmem BOs from host, but doing it only for imported dma-bufs. Mark all shmem BOs as attached, not just dma-bufs. This is a minor correction since detachment of a non-dmabuf BOs not supported today. Signed-off-by: Dmitry Osipenko Acked-by: Vivek Kasireddy Link: https://patchwork.freedesktop.org/patch/msgid/20241129155357.2265357-1-dmitry.osipenko@collabora.com --- drivers/gpu/drm/virtio/virtgpu_prime.c | 1 - drivers/gpu/drm/virtio/virtgpu_vq.c | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index f92133a01195..483707630861 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -250,7 +250,6 @@ static int virtgpu_dma_buf_init_obj(struct drm_device *dev, virtio_gpu_cmd_resource_create_blob(vgdev, bo, ¶ms, ents, nents); bo->guest_blob = true; - bo->attached = true; dma_buf_unpin(attach); dma_resv_unlock(resv); diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index ad91624df42d..062639250a4e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -1300,6 +1300,9 @@ virtio_gpu_cmd_resource_create_blob(struct virtio_gpu_device *vgdev, virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); bo->created = true; + + if (nents) + bo->attached = true; } void virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_device *vgdev, -- cgit v1.2.3-59-g8ed1b From 2ef1c8c5de40316ba65051940e587157385e10c0 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 2 Dec 2024 08:39:55 +0300 Subject: drm/virtio: Factor out common dmabuf unmapping code Move out dmabuf detachment and unmapping into separate function. This removes duplicated code and there is no need to check the GEM's kref now, since both bo->attached and bo->sgt are unset under held reservation lock. Signed-off-by: Dmitry Osipenko Acked-by: Vivek Kasireddy Link: https://patchwork.freedesktop.org/patch/msgid/20241202053955.2451321-1-dmitry.osipenko@collabora.com --- drivers/gpu/drm/virtio/virtgpu_prime.c | 35 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 483707630861..fe6a0b018571 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -184,6 +184,23 @@ int virtgpu_dma_buf_import_sgt(struct virtio_gpu_mem_entry **ents, return 0; } +static void virtgpu_dma_buf_unmap(struct virtio_gpu_object *bo) +{ + struct dma_buf_attachment *attach = bo->base.base.import_attach; + + dma_resv_assert_held(attach->dmabuf->resv); + + if (bo->created) { + virtio_gpu_detach_object_fenced(bo); + + if (bo->sgt) + dma_buf_unmap_attachment(attach, bo->sgt, + DMA_BIDIRECTIONAL); + + bo->sgt = NULL; + } +} + static void virtgpu_dma_buf_free_obj(struct drm_gem_object *obj) { struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); @@ -194,13 +211,7 @@ static void virtgpu_dma_buf_free_obj(struct drm_gem_object *obj) struct dma_buf *dmabuf = attach->dmabuf; dma_resv_lock(dmabuf->resv, NULL); - - virtio_gpu_detach_object_fenced(bo); - - if (bo->sgt) - dma_buf_unmap_attachment(attach, bo->sgt, - DMA_BIDIRECTIONAL); - + virtgpu_dma_buf_unmap(bo); dma_resv_unlock(dmabuf->resv); dma_buf_detach(dmabuf, attach); @@ -273,15 +284,7 @@ static void virtgpu_dma_buf_move_notify(struct dma_buf_attachment *attach) struct drm_gem_object *obj = attach->importer_priv; struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); - if (bo->created && kref_read(&obj->refcount)) { - virtio_gpu_detach_object_fenced(bo); - - if (bo->sgt) - dma_buf_unmap_attachment(attach, bo->sgt, - DMA_BIDIRECTIONAL); - - bo->sgt = NULL; - } + virtgpu_dma_buf_unmap(bo); } static const struct dma_buf_attach_ops virtgpu_dma_buf_attach_ops = { -- cgit v1.2.3-59-g8ed1b From 178ada9d6e90637667a7410dd7fe75fbbe2cd4c5 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 15 Nov 2024 10:21:51 +0000 Subject: dma-fence: Add a single fence fast path for fence merging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Testing some workloads in two different scenarios, such as games running under Gamescope on a Steam Deck, or vkcube under a Plasma desktop, shows that in a significant portion of calls the dma_fence_unwrap_merge helper is called with just a single unsignalled fence. Therefore it is worthile to add a fast path for that case and so bypass the memory allocation and insertion sort attempts. Tested scenarios: 1) Hogwarts Legacy under Gamescope ~1500 calls per second to __dma_fence_unwrap_merge. Percentages per number of fences buckets, before and after checking for signalled status, sorting and flattening: N Before After 0 0.85% 1 69.80% -> The new fast path. 2-9 29.36% 9% (Ie. 91% of this bucket flattened to 1 fence) 10-19 20-40 50+ 2) Cyberpunk 2077 under Gamescope ~2400 calls per second. N Before After 0 0.71% 1 52.53% -> The new fast path. 2-9 44.38% 50.60% (Ie. half resolved to a single fence) 10-19 2.34% 20-40 0.06% 50+ 3) vkcube under Plasma 90 calls per second. N Before After 0 1 2-9 100% 0% (Ie. all resolved to a single fence) 10-19 20-40 50+ In the case of vkcube all invocations in the 2-9 bucket were actually just two input fences. v2: * Correct local variable name and hold on to unsignaled reference. (Chistian) Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Friedrich Vock Reviewed-by: Christian König Signed-off-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20241115102153.1980-4-tursulin@igalia.com --- drivers/dma-buf/dma-fence-unwrap.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c index 6345062731f1..2a059ac0ed27 100644 --- a/drivers/dma-buf/dma-fence-unwrap.c +++ b/drivers/dma-buf/dma-fence-unwrap.c @@ -84,8 +84,8 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, struct dma_fence **fences, struct dma_fence_unwrap *iter) { + struct dma_fence *tmp, *unsignaled = NULL, **array; struct dma_fence_array *result; - struct dma_fence *tmp, **array; ktime_t timestamp; int i, j, count; @@ -94,6 +94,8 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, for (i = 0; i < num_fences; ++i) { dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) { if (!dma_fence_is_signaled(tmp)) { + dma_fence_put(unsignaled); + unsignaled = dma_fence_get(tmp); ++count; } else { ktime_t t = dma_fence_timestamp(tmp); @@ -107,9 +109,16 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, /* * If we couldn't find a pending fence just return a private signaled * fence with the timestamp of the last signaled one. + * + * Or if there was a single unsignaled fence left we can return it + * directly and early since that is a major path on many workloads. */ if (count == 0) return dma_fence_allocate_private_stub(timestamp); + else if (count == 1) + return unsignaled; + + dma_fence_put(unsignaled); array = kmalloc_array(count, sizeof(*array), GFP_KERNEL); if (!array) -- cgit v1.2.3-59-g8ed1b From b1cce631e61fcf3e1bc77ace05f10d00c737af9a Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 15 Nov 2024 10:21:52 +0000 Subject: dma-buf: add selftest for fence order after merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test which double checks that fences are in the expected order after a merge. While at it also switch to using a mock array for the complex test instead of a merge. Signed-off-by: Christian König Signed-off-by: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20241115102153.1980-5-tursulin@igalia.com --- drivers/dma-buf/st-dma-fence-unwrap.c | 69 ++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c b/drivers/dma-buf/st-dma-fence-unwrap.c index f0cee984b6c7..876eabddb08f 100644 --- a/drivers/dma-buf/st-dma-fence-unwrap.c +++ b/drivers/dma-buf/st-dma-fence-unwrap.c @@ -304,6 +304,72 @@ error_put_f1: return err; } +static int unwrap_merge_order(void *arg) +{ + struct dma_fence *fence, *f1, *f2, *a1, *a2, *c1, *c2; + struct dma_fence_unwrap iter; + int err = 0; + + f1 = mock_fence(); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = mock_fence(); + if (!f2) { + dma_fence_put(f1); + return -ENOMEM; + } + + dma_fence_enable_sw_signaling(f2); + + a1 = mock_array(2, f1, f2); + if (!a1) + return -ENOMEM; + + c1 = mock_chain(NULL, dma_fence_get(f1)); + if (!c1) + goto error_put_a1; + + c2 = mock_chain(c1, dma_fence_get(f2)); + if (!c2) + goto error_put_a1; + + /* + * The fences in the chain are the same as in a1 but in oposite order, + * the dma_fence_merge() function should be able to handle that. + */ + a2 = dma_fence_unwrap_merge(a1, c2); + + dma_fence_unwrap_for_each(fence, &iter, a2) { + if (fence == f1) { + f1 = NULL; + if (!f2) + pr_err("Unexpected order!\n"); + } else if (fence == f2) { + f2 = NULL; + if (f1) + pr_err("Unexpected order!\n"); + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f1 || f2) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(a2); + return err; + +error_put_a1: + dma_fence_put(a1); + return -ENOMEM; +} + static int unwrap_merge_complex(void *arg) { struct dma_fence *fence, *f1, *f2, *f3, *f4, *f5; @@ -327,7 +393,7 @@ static int unwrap_merge_complex(void *arg) goto error_put_f2; /* The resulting array has the fences in reverse */ - f4 = dma_fence_unwrap_merge(f2, f1); + f4 = mock_array(2, dma_fence_get(f2), dma_fence_get(f1)); if (!f4) goto error_put_f3; @@ -375,6 +441,7 @@ int dma_fence_unwrap(void) SUBTEST(unwrap_chain), SUBTEST(unwrap_chain_array), SUBTEST(unwrap_merge), + SUBTEST(unwrap_merge_order), SUBTEST(unwrap_merge_complex), }; -- cgit v1.2.3-59-g8ed1b From d2a0b1bc5773d3124ef7bee886fce1bb59fd9b76 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 15 Nov 2024 10:21:53 +0000 Subject: dma-fence: Add some more fence-merge-unwrap tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far all tests use seqno one and only vary the context. Lets add some tests which vary the seqno too. Signed-off-by: Tvrtko Ursulin Reviewed-by: Christian König Signed-off-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20241115102153.1980-6-tursulin@igalia.com --- drivers/dma-buf/st-dma-fence-unwrap.c | 199 +++++++++++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c b/drivers/dma-buf/st-dma-fence-unwrap.c index 876eabddb08f..a3be888ae2e8 100644 --- a/drivers/dma-buf/st-dma-fence-unwrap.c +++ b/drivers/dma-buf/st-dma-fence-unwrap.c @@ -28,7 +28,7 @@ static const struct dma_fence_ops mock_ops = { .get_timeline_name = mock_name, }; -static struct dma_fence *mock_fence(void) +static struct dma_fence *__mock_fence(u64 context, u64 seqno) { struct mock_fence *f; @@ -37,12 +37,16 @@ static struct dma_fence *mock_fence(void) return NULL; spin_lock_init(&f->lock); - dma_fence_init(&f->base, &mock_ops, &f->lock, - dma_fence_context_alloc(1), 1); + dma_fence_init(&f->base, &mock_ops, &f->lock, context, seqno); return &f->base; } +static struct dma_fence *mock_fence(void) +{ + return __mock_fence(dma_fence_context_alloc(1), 1); +} + static struct dma_fence *mock_array(unsigned int num_fences, ...) { struct dma_fence_array *array; @@ -304,6 +308,111 @@ error_put_f1: return err; } +static int unwrap_merge_duplicate(void *arg) +{ + struct dma_fence *fence, *f1, *f2; + struct dma_fence_unwrap iter; + int err = 0; + + f1 = mock_fence(); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = dma_fence_unwrap_merge(f1, f1); + if (!f2) { + err = -ENOMEM; + goto error_put_f1; + } + + dma_fence_unwrap_for_each(fence, &iter, f2) { + if (fence == f1) { + dma_fence_put(f1); + f1 = NULL; + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f1) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(f2); +error_put_f1: + dma_fence_put(f1); + return err; +} + +static int unwrap_merge_seqno(void *arg) +{ + struct dma_fence *fence, *f1, *f2, *f3, *f4; + struct dma_fence_unwrap iter; + int err = 0; + u64 ctx[2]; + + ctx[0] = dma_fence_context_alloc(1); + ctx[1] = dma_fence_context_alloc(1); + + f1 = __mock_fence(ctx[1], 1); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = __mock_fence(ctx[1], 2); + if (!f2) { + err = -ENOMEM; + goto error_put_f1; + } + + dma_fence_enable_sw_signaling(f2); + + f3 = __mock_fence(ctx[0], 1); + if (!f3) { + err = -ENOMEM; + goto error_put_f2; + } + + dma_fence_enable_sw_signaling(f3); + + f4 = dma_fence_unwrap_merge(f1, f2, f3); + if (!f4) { + err = -ENOMEM; + goto error_put_f3; + } + + dma_fence_unwrap_for_each(fence, &iter, f4) { + if (fence == f3 && f2) { + dma_fence_put(f3); + f3 = NULL; + } else if (fence == f2 && !f3) { + dma_fence_put(f2); + f2 = NULL; + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f2 || f3) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(f4); +error_put_f3: + dma_fence_put(f3); +error_put_f2: + dma_fence_put(f2); +error_put_f1: + dma_fence_put(f1); + return err; +} + static int unwrap_merge_order(void *arg) { struct dma_fence *fence, *f1, *f2, *a1, *a2, *c1, *c2; @@ -433,6 +542,87 @@ error_put_f1: return err; } +static int unwrap_merge_complex_seqno(void *arg) +{ + struct dma_fence *fence, *f1, *f2, *f3, *f4, *f5, *f6, *f7; + struct dma_fence_unwrap iter; + int err = -ENOMEM; + u64 ctx[2]; + + ctx[0] = dma_fence_context_alloc(1); + ctx[1] = dma_fence_context_alloc(1); + + f1 = __mock_fence(ctx[0], 2); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = __mock_fence(ctx[1], 1); + if (!f2) + goto error_put_f1; + + dma_fence_enable_sw_signaling(f2); + + f3 = __mock_fence(ctx[0], 1); + if (!f3) + goto error_put_f2; + + dma_fence_enable_sw_signaling(f3); + + f4 = __mock_fence(ctx[1], 2); + if (!f4) + goto error_put_f3; + + dma_fence_enable_sw_signaling(f4); + + f5 = mock_array(2, dma_fence_get(f1), dma_fence_get(f2)); + if (!f5) + goto error_put_f4; + + f6 = mock_array(2, dma_fence_get(f3), dma_fence_get(f4)); + if (!f6) + goto error_put_f5; + + f7 = dma_fence_unwrap_merge(f5, f6); + if (!f7) + goto error_put_f6; + + err = 0; + dma_fence_unwrap_for_each(fence, &iter, f7) { + if (fence == f1 && f4) { + dma_fence_put(f1); + f1 = NULL; + } else if (fence == f4 && !f1) { + dma_fence_put(f4); + f4 = NULL; + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f1 || f4) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(f7); +error_put_f6: + dma_fence_put(f6); +error_put_f5: + dma_fence_put(f5); +error_put_f4: + dma_fence_put(f4); +error_put_f3: + dma_fence_put(f3); +error_put_f2: + dma_fence_put(f2); +error_put_f1: + dma_fence_put(f1); + return err; +} + int dma_fence_unwrap(void) { static const struct subtest tests[] = { @@ -441,8 +631,11 @@ int dma_fence_unwrap(void) SUBTEST(unwrap_chain), SUBTEST(unwrap_chain_array), SUBTEST(unwrap_merge), + SUBTEST(unwrap_merge_duplicate), + SUBTEST(unwrap_merge_seqno), SUBTEST(unwrap_merge_order), SUBTEST(unwrap_merge_complex), + SUBTEST(unwrap_merge_complex_seqno), }; return subtests(tests, NULL); -- cgit v1.2.3-59-g8ed1b From 3ac197e4d7ada579a1a8fed36f7f27eb1c231dd2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:20 +0200 Subject: drm/i915/scaler: Extract skl_scaler_min_src_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SKL_MIN_*SRC_* defines just make things hard to read. Get rid of them and introduce an easy to read function in their place. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-2-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/skl_scaler.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index ae21fce534dc..8b5b7993a492 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -76,9 +76,7 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) return ((phase >> 2) & PS_PHASE_MASK) | trip; } -#define SKL_MIN_SRC_W 8 #define SKL_MAX_SRC_W 4096 -#define SKL_MIN_SRC_H 8 #define SKL_MAX_SRC_H 4096 #define SKL_MIN_DST_W 8 #define SKL_MAX_DST_W 4096 @@ -96,8 +94,18 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) #define MTL_MAX_SRC_H 8192 #define MTL_MAX_DST_W 8192 #define MTL_MAX_DST_H 8192 -#define SKL_MIN_YUV_420_SRC_W 16 -#define SKL_MIN_YUV_420_SRC_H 16 + +static void skl_scaler_min_src_size(const struct drm_format_info *format, + u64 modifier, int *min_w, int *min_h) +{ + if (format && intel_format_info_is_yuv_semiplanar(format, modifier)) { + *min_w = 16; + *min_h = 16; + } else { + *min_w = 8; + *min_h = 8; + } +} static int skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, @@ -163,15 +171,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, return 0; } - if (format && intel_format_info_is_yuv_semiplanar(format, modifier) && - (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) { - drm_dbg_kms(display->drm, - "Planar YUV: src dimensions not met\n"); - return -EINVAL; - } + skl_scaler_min_src_size(format, modifier, &min_src_w, &min_src_h); - min_src_w = SKL_MIN_SRC_W; - min_src_h = SKL_MIN_SRC_H; min_dst_w = SKL_MIN_DST_W; min_dst_h = SKL_MIN_DST_H; -- cgit v1.2.3-59-g8ed1b From 24c095f6958acebefabee4aad20ee5a98cfb46fb Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:21 +0200 Subject: drm/i915/scaler: Extract skl_scaler_max_src_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SKL_MAX_SRC_* defines just make things hard to read. Get rid of them and introduce an easy to read function in their place. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-3-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/skl_scaler.c | 37 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 8b5b7993a492..d6bef6578867 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -76,22 +76,14 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) return ((phase >> 2) & PS_PHASE_MASK) | trip; } -#define SKL_MAX_SRC_W 4096 -#define SKL_MAX_SRC_H 4096 #define SKL_MIN_DST_W 8 #define SKL_MAX_DST_W 4096 #define SKL_MIN_DST_H 8 #define SKL_MAX_DST_H 4096 -#define ICL_MAX_SRC_W 5120 -#define ICL_MAX_SRC_H 4096 #define ICL_MAX_DST_W 5120 #define ICL_MAX_DST_H 4096 -#define TGL_MAX_SRC_W 5120 -#define TGL_MAX_SRC_H 8192 #define TGL_MAX_DST_W 8192 #define TGL_MAX_DST_H 8192 -#define MTL_MAX_SRC_W 4096 -#define MTL_MAX_SRC_H 8192 #define MTL_MAX_DST_W 8192 #define MTL_MAX_DST_H 8192 @@ -107,6 +99,26 @@ static void skl_scaler_min_src_size(const struct drm_format_info *format, } } +static void skl_scaler_max_src_size(struct intel_crtc *crtc, + int *max_w, int *max_h) +{ + struct intel_display *display = to_intel_display(crtc); + + if (DISPLAY_VER(display) >= 14) { + *max_w = 4096; + *max_h = 8192; + } else if (DISPLAY_VER(display) >= 12) { + *max_w = 5120; + *max_h = 8192; + } else if (DISPLAY_VER(display) == 11) { + *max_w = 5120; + *max_h = 4096; + } else { + *max_w = 4096; + *max_h = 4096; + } +} + static int skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, unsigned int scaler_user, int *scaler_id, @@ -172,28 +184,21 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, } skl_scaler_min_src_size(format, modifier, &min_src_w, &min_src_h); + skl_scaler_max_src_size(crtc, &max_src_w, &max_src_h); min_dst_w = SKL_MIN_DST_W; min_dst_h = SKL_MIN_DST_H; if (DISPLAY_VER(display) < 11) { - max_src_w = SKL_MAX_SRC_W; - max_src_h = SKL_MAX_SRC_H; max_dst_w = SKL_MAX_DST_W; max_dst_h = SKL_MAX_DST_H; } else if (DISPLAY_VER(display) < 12) { - max_src_w = ICL_MAX_SRC_W; - max_src_h = ICL_MAX_SRC_H; max_dst_w = ICL_MAX_DST_W; max_dst_h = ICL_MAX_DST_H; } else if (DISPLAY_VER(display) < 14) { - max_src_w = TGL_MAX_SRC_W; - max_src_h = TGL_MAX_SRC_H; max_dst_w = TGL_MAX_DST_W; max_dst_h = TGL_MAX_DST_H; } else { - max_src_w = MTL_MAX_SRC_W; - max_src_h = MTL_MAX_SRC_H; max_dst_w = MTL_MAX_DST_W; max_dst_h = MTL_MAX_DST_H; } -- cgit v1.2.3-59-g8ed1b From 9313b0bee09b6fdff4fb087090e57e44fcfd4ab3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:22 +0200 Subject: drm/i915/scaler: Extract skl_scaler_min_dst_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SKL_MIN_DST_* defines just make things hard to read. Get rid of them and introduce an easy to read function in their place. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-4-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/skl_scaler.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index d6bef6578867..cabbf4860cb3 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -76,9 +76,7 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) return ((phase >> 2) & PS_PHASE_MASK) | trip; } -#define SKL_MIN_DST_W 8 #define SKL_MAX_DST_W 4096 -#define SKL_MIN_DST_H 8 #define SKL_MAX_DST_H 4096 #define ICL_MAX_DST_W 5120 #define ICL_MAX_DST_H 4096 @@ -119,6 +117,12 @@ static void skl_scaler_max_src_size(struct intel_crtc *crtc, } } +static void skl_scaler_min_dst_size(int *min_w, int *min_h) +{ + *min_w = 8; + *min_h = 8; +} + static int skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, unsigned int scaler_user, int *scaler_id, @@ -186,8 +190,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, skl_scaler_min_src_size(format, modifier, &min_src_w, &min_src_h); skl_scaler_max_src_size(crtc, &max_src_w, &max_src_h); - min_dst_w = SKL_MIN_DST_W; - min_dst_h = SKL_MIN_DST_H; + skl_scaler_min_dst_size(&min_dst_w, &min_dst_h); if (DISPLAY_VER(display) < 11) { max_dst_w = SKL_MAX_DST_W; -- cgit v1.2.3-59-g8ed1b From c5877587a2a93de3ebf0cb981f02ed3d2fee3ee3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:23 +0200 Subject: drm/i915/scaler: Extract skl_scaler_max_dst_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SKL_MAX_DST_* defines just make things hard to read. Get rid of them and introduce an easy to read function in their place. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-5-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/skl_scaler.c | 44 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index cabbf4860cb3..0bc82a047510 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -76,15 +76,6 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) return ((phase >> 2) & PS_PHASE_MASK) | trip; } -#define SKL_MAX_DST_W 4096 -#define SKL_MAX_DST_H 4096 -#define ICL_MAX_DST_W 5120 -#define ICL_MAX_DST_H 4096 -#define TGL_MAX_DST_W 8192 -#define TGL_MAX_DST_H 8192 -#define MTL_MAX_DST_W 8192 -#define MTL_MAX_DST_H 8192 - static void skl_scaler_min_src_size(const struct drm_format_info *format, u64 modifier, int *min_w, int *min_h) { @@ -123,6 +114,26 @@ static void skl_scaler_min_dst_size(int *min_w, int *min_h) *min_h = 8; } +static void skl_scaler_max_dst_size(struct intel_crtc *crtc, + int *max_w, int *max_h) +{ + struct intel_display *display = to_intel_display(crtc); + + if (DISPLAY_VER(display) >= 14) { + *max_w = 8192; + *max_h = 8192; + } else if (DISPLAY_VER(display) >= 12) { + *max_w = 8192; + *max_h = 8192; + } else if (DISPLAY_VER(display) == 11) { + *max_w = 5120; + *max_h = 4096; + } else { + *max_w = 4096; + *max_h = 4096; + } +} + static int skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, unsigned int scaler_user, int *scaler_id, @@ -191,20 +202,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, skl_scaler_max_src_size(crtc, &max_src_w, &max_src_h); skl_scaler_min_dst_size(&min_dst_w, &min_dst_h); - - if (DISPLAY_VER(display) < 11) { - max_dst_w = SKL_MAX_DST_W; - max_dst_h = SKL_MAX_DST_H; - } else if (DISPLAY_VER(display) < 12) { - max_dst_w = ICL_MAX_DST_W; - max_dst_h = ICL_MAX_DST_H; - } else if (DISPLAY_VER(display) < 14) { - max_dst_w = TGL_MAX_DST_W; - max_dst_h = TGL_MAX_DST_H; - } else { - max_dst_w = MTL_MAX_DST_W; - max_dst_h = MTL_MAX_DST_H; - } + skl_scaler_max_dst_size(crtc, &max_dst_w, &max_dst_h); /* range checks */ if (src_w < min_src_w || src_h < min_src_h || -- cgit v1.2.3-59-g8ed1b From d4dbabd4251a93f98f8f4e72ad57f35adbd08e00 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:24 +0200 Subject: drm/i915/scaler: Nuke redundant code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tgl+ and mtl+ numbers in skl_scaler_max_dst_size() are identical. Combine them to a single piece of code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-6-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/skl_scaler.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 0bc82a047510..cbc71e44fcbb 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -119,10 +119,7 @@ static void skl_scaler_max_dst_size(struct intel_crtc *crtc, { struct intel_display *display = to_intel_display(crtc); - if (DISPLAY_VER(display) >= 14) { - *max_w = 8192; - *max_h = 8192; - } else if (DISPLAY_VER(display) >= 12) { + if (DISPLAY_VER(display) >= 12) { *max_w = 8192; *max_h = 8192; } else if (DISPLAY_VER(display) == 11) { -- cgit v1.2.3-59-g8ed1b From 3040274f7e2b651a4e65082b57b7174a49bcc593 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:25 +0200 Subject: drm/i915/scaler: Pimp scaler debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the standard "[CRTC:...]" information in the scaler debugs to make life easier. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-7-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/skl_scaler.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index cbc71e44fcbb..f6d76ef1a854 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -166,7 +166,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, if (DISPLAY_VER(display) >= 9 && crtc_state->hw.enable && need_scaler && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { drm_dbg_kms(display->drm, - "Pipe/Plane scaling not supported with IF-ID mode\n"); + "[CRTC:%d:%s] scaling not supported with IF-ID mode\n", + crtc->base.base.id, crtc->base.name); return -EINVAL; } @@ -186,8 +187,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, scaler_state->scalers[*scaler_id].in_use = false; drm_dbg_kms(display->drm, - "scaler_user index %u.%u: " + "[CRTC:%d:%s] scaler_user index %u.%u: " "Staged freeing scaler id %d scaler_users = 0x%x\n", + crtc->base.base.id, crtc->base.name, crtc->pipe, scaler_user, *scaler_id, scaler_state->scaler_users); *scaler_id = -1; @@ -207,8 +209,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, src_w > max_src_w || src_h > max_src_h || dst_w > max_dst_w || dst_h > max_dst_h) { drm_dbg_kms(display->drm, - "scaler_user index %u.%u: src %ux%u dst %ux%u " + "[CRTC:%d:%s] scaler_user index %u.%u: src %ux%u dst %ux%u " "size is out of scaler range\n", + crtc->base.base.id, crtc->base.name, crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h); return -EINVAL; @@ -224,16 +227,18 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, */ if (pipe_src_w > max_dst_w || pipe_src_h > max_dst_h) { drm_dbg_kms(display->drm, - "scaler_user index %u.%u: pipe src size %ux%u " + "[CRTC:%d:%s] scaler_user index %u.%u: pipe src size %ux%u " "is out of scaler range\n", + crtc->base.base.id, crtc->base.name, crtc->pipe, scaler_user, pipe_src_w, pipe_src_h); return -EINVAL; } /* mark this plane as a scaler user in crtc_state */ scaler_state->scaler_users |= (1 << scaler_user); - drm_dbg_kms(display->drm, "scaler_user index %u.%u: " + drm_dbg_kms(display->drm, "[CRTC:%d:%s] scaler_user index %u.%u: " "staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n", + crtc->base.base.id, crtc->base.name, crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h, scaler_state->scaler_users); @@ -421,8 +426,8 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat if (hscale < 0 || vscale < 0) { drm_dbg_kms(display->drm, - "Scaler %d doesn't support required plane scaling\n", - *scaler_id); + "[CRTC:%d:%s] scaler %d doesn't support required plane scaling\n", + crtc->base.base.id, crtc->base.name, *scaler_id); drm_rect_debug_print("src: ", src, true); drm_rect_debug_print("dst: ", dst, false); @@ -430,7 +435,8 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat } } - drm_dbg_kms(display->drm, "Attached scaler id %u.%u to %s:%d\n", + drm_dbg_kms(display->drm, "[CRTC:%d:%s] attached scaler id %u.%u to %s:%d\n", + crtc->base.base.id, crtc->base.name, crtc->pipe, *scaler_id, name, idx); scaler_state->scalers[*scaler_id].mode = mode; @@ -530,7 +536,8 @@ int intel_atomic_setup_scalers(struct intel_atomic_state *state, /* fail if required scalers > available scalers */ if (num_scalers_need > crtc->num_scalers) { drm_dbg_kms(display->drm, - "Too many scaling requests %d > %d\n", + "[CRTC:%d:%s] too many scaling requests %d > %d\n", + crtc->base.base.id, crtc->base.name, num_scalers_need, crtc->num_scalers); return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From 49b14a1256a365f288abcd438750cd102a9dadb0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:26 +0200 Subject: drm/i915/scaler: s/excdeed/exceed/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix typo s/excdeed/exceed/ Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-8-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/skl_scaler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index f6d76ef1a854..79739357162c 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -64,7 +64,7 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) /* * Hardware initial phase limited to [-0.5:1.5]. * Since the max hardware scale factor is 3.0, we - * should never actually excdeed 1.0 here. + * should never actually exceed 1.0 here. */ WARN_ON(phase < -0x8000 || phase > 0x18000); -- cgit v1.2.3-59-g8ed1b From c0eac88092642e49be3b5d47eb5d5a963199b024 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2024 15:08:27 +0200 Subject: drm/i915/scaler: Add scaler tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some tracpoints around skl+ scaler programming to help with debugging. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241219130827.22830-9-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_display_trace.h | 99 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/skl_scaler.c | 8 ++ 2 files changed, 107 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 338b9f7b20b8..54a6e2a46b82 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -489,6 +489,105 @@ TRACE_EVENT(intel_plane_disable_arm, __entry->frame, __entry->scanline) ); +TRACE_EVENT(intel_plane_scaler_update_arm, + TP_PROTO(struct intel_plane *plane, + int scaler_id, int x, int y, int w, int h), + TP_ARGS(plane, scaler_id, x, y, w, h), + + TP_STRUCT__entry( + __string(dev, __dev_name_kms(plane)) + __field(char, pipe_name) + __field(int, scaler_id) + __field(u32, frame) + __field(u32, scanline) + __field(int, x) + __field(int, y) + __field(int, w) + __field(int, h) + __string(name, plane->base.name) + ), + + TP_fast_assign( + struct intel_display *display = to_intel_display(plane); + struct intel_crtc *crtc = intel_crtc_for_pipe(display, plane->pipe); + __assign_str(dev); + __assign_str(name); + __entry->pipe_name = pipe_name(crtc->pipe); + __entry->scaler_id = scaler_id; + __entry->frame = intel_crtc_get_vblank_counter(crtc); + __entry->scanline = intel_get_crtc_scanline(crtc); + __entry->x = x; + __entry->y = y; + __entry->w = w; + __entry->h = h; + ), + + TP_printk("dev %s, pipe %c, scaler %d, plane %s, frame=%u, scanline=%u, " DRM_RECT_FMT, + __get_str(dev), __entry->pipe_name, __entry->scaler_id, + __get_str(name), __entry->frame, __entry->scanline, + __entry->w, __entry->h, __entry->x, __entry->y) +); + +TRACE_EVENT(intel_pipe_scaler_update_arm, + TP_PROTO(struct intel_crtc *crtc, int scaler_id, + int x, int y, int w, int h), + TP_ARGS(crtc, scaler_id, x, y, w, h), + + TP_STRUCT__entry( + __string(dev, __dev_name_kms(crtc)) + __field(char, pipe_name) + __field(int, scaler_id) + __field(u32, frame) + __field(u32, scanline) + __field(int, x) + __field(int, y) + __field(int, w) + __field(int, h) + ), + + TP_fast_assign( + __assign_str(dev); + __entry->pipe_name = pipe_name(crtc->pipe); + __entry->scaler_id = scaler_id; + __entry->frame = intel_crtc_get_vblank_counter(crtc); + __entry->scanline = intel_get_crtc_scanline(crtc); + __entry->x = x; + __entry->y = y; + __entry->w = w; + __entry->h = h; + ), + + TP_printk("dev %s, pipe %c, scaler %d frame=%u, scanline=%u, " DRM_RECT_FMT, + __get_str(dev), __entry->pipe_name, __entry->scaler_id, + __entry->frame, __entry->scanline, + __entry->w, __entry->h, __entry->x, __entry->y) +); + +TRACE_EVENT(intel_scaler_disable_arm, + TP_PROTO(struct intel_crtc *crtc, int scaler_id), + TP_ARGS(crtc, scaler_id), + + TP_STRUCT__entry( + __string(dev, __dev_name_kms(crtc)) + __field(char, pipe_name) + __field(int, scaler_id) + __field(u32, frame) + __field(u32, scanline) + ), + + TP_fast_assign( + __assign_str(dev); + __entry->pipe_name = pipe_name(crtc->pipe); + __entry->scaler_id = scaler_id; + __entry->frame = intel_crtc_get_vblank_counter(crtc); + __entry->scanline = intel_get_crtc_scanline(crtc); + ), + + TP_printk("dev %s, pipe %c, scaler %d, frame=%u, scanline=%u", + __get_str(dev), __entry->pipe_name, __entry->scaler_id, + __entry->frame, __entry->scanline) +); + TRACE_EVENT(intel_fbc_activate, TP_PROTO(struct intel_plane *plane), TP_ARGS(plane), diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 79739357162c..a11e09a15e23 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -6,6 +6,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_de.h" +#include "intel_display_trace.h" #include "intel_display_types.h" #include "intel_fb.h" #include "skl_scaler.h" @@ -706,6 +707,8 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0); + trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height); + skl_scaler_setup_filter(display, pipe, id, 0, crtc_state->hw.scaling_filter); @@ -770,6 +773,9 @@ skl_program_plane_scaler(struct intel_plane *plane, ps_ctrl = PS_SCALER_EN | PS_BINDING_PLANE(plane->id) | scaler->mode | skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0); + trace_intel_plane_scaler_update_arm(plane, scaler_id, + crtc_x, crtc_y, crtc_w, crtc_h); + skl_scaler_setup_filter(display, pipe, scaler_id, 0, plane_state->hw.scaling_filter); @@ -788,6 +794,8 @@ static void skl_detach_scaler(struct intel_crtc *crtc, int id) { struct intel_display *display = to_intel_display(crtc); + trace_intel_scaler_disable_arm(crtc, id); + intel_de_write_fw(display, SKL_PS_CTRL(crtc->pipe, id), 0); intel_de_write_fw(display, SKL_PS_WIN_POS(crtc->pipe, id), 0); intel_de_write_fw(display, SKL_PS_WIN_SZ(crtc->pipe, id), 0); -- cgit v1.2.3-59-g8ed1b From 97395ce76edcce4d39419e90a65d84960fd48aee Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 8 Jan 2025 17:43:29 -0600 Subject: drm/nouveau: fix kernel-doc comments Fix some malformed kernel-doc comments that were added in a recent commit. Also, kernel-doc does not support global variables, so change those kernel-doc comments into regular comments. Fixes: 214c9539cf2f ("drm/nouveau: expose GSP-RM logging buffers via debugfs") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202412310834.jtCJj4oz-lkp@intel.com/ Signed-off-by: Timur Tabi Reviewed-by: Ben Skeggs Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250108234329.842256-1-ttabi@nvidia.com --- drivers/gpu/drm/nouveau/nouveau_drm.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 21d2d9ca5e85..8c970f018c00 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -118,7 +118,7 @@ static struct drm_driver driver_platform; #ifdef CONFIG_DEBUG_FS struct dentry *nouveau_debugfs_root; -/** +/* * gsp_logs - list of nvif_log GSP-RM logging buffers * * Head pointer to a a list of nvif_log buffers that is created for each GPU diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 58502102926b..10fe2d15b5ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -1111,7 +1111,7 @@ enum registry_type { #define REGISTRY_MAX_KEY_LENGTH 64 /** - * registry_list_entry - linked list member for a registry key/value + * struct registry_list_entry - linked list member for a registry key/value * @head: list_head struct * @type: dword, binary, or string * @klen: the length of name of the key @@ -1327,7 +1327,7 @@ struct nv_gsp_registry_entries { u32 value; }; -/** +/* * r535_registry_entries - required registry entries for GSP-RM * * This array lists registry entries that are required for GSP-RM to @@ -2101,7 +2101,7 @@ MODULE_PARM_DESC(keep_gsp_logging, #define NV_GSP_MSG_EVENT_UCODE_LIBOS_CLASS_PMU 0xf3d722 /** - * rpc_ucode_libos_print_v1E_08 - RPC payload for libos print buffers + * struct rpc_ucode_libos_print_v1e_08 - RPC payload for libos print buffers * @ucode_eng_desc: the engine descriptor * @libos_print_buf_size: the size of the libos_print_buf[] * @libos_print_buf: the actual buffer @@ -2162,7 +2162,7 @@ r535_gsp_msg_libos_print(void *priv, u32 fn, void *repv, u32 repc) } /** - * create_debufgs - create a blob debugfs entry + * create_debugfs - create a blob debugfs entry * @gsp: gsp pointer * @name: name of this dentry * @blob: blob wrapper @@ -2788,6 +2788,10 @@ static bool is_empty(const struct debugfs_blob_wrapper *b) /** * r535_gsp_copy_log - preserve the logging buffers in a blob + * @parent: the top-level dentry for this GPU + * @name: name of debugfs entry to create + * @s: original wrapper object to copy from + * @t: new wrapper object to copy to * * When GSP shuts down, the nvkm_gsp object and all its memory is deleted. * To preserve the logging buffers, the buffers need to be copied, but only -- cgit v1.2.3-59-g8ed1b From 0c2768bf818904db705ff18674f771c3c4d8bbca Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Thu, 9 Jan 2025 11:48:11 -0800 Subject: accel/amdxdna: Return error when setting clock failed for npu1 Due to miss returning error when setting clock, the smatch static checker reports warning: drivers/accel/amdxdna/aie2_smu.c:68 npu1_set_dpm() error: uninitialized symbol 'freq'. Fixes: f4d7b8a6bc8c ("accel/amdxdna: Enhance power management settings") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/dri-devel/202267d0-882e-4593-b58d-be9274592f9b@stanley.mountain/ Signed-off-by: Lizhi Hou Reviewed-by: Mario Limonciello Signed-off-by: Mario Limonciello Link: https://patchwork.freedesktop.org/patch/msgid/20250109194811.499505-1-lizhi.hou@amd.com --- drivers/accel/amdxdna/aie2_smu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/accel/amdxdna/aie2_smu.c b/drivers/accel/amdxdna/aie2_smu.c index 73388443c676..d303701b0ded 100644 --- a/drivers/accel/amdxdna/aie2_smu.c +++ b/drivers/accel/amdxdna/aie2_smu.c @@ -64,6 +64,7 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) if (ret) { XDNA_ERR(ndev->xdna, "Set npu clock to %d failed, ret %d\n", ndev->priv->dpm_clk_tbl[dpm_level].npuclk, ret); + return ret; } ndev->npuclk_freq = freq; @@ -72,6 +73,7 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) if (ret) { XDNA_ERR(ndev->xdna, "Set h clock to %d failed, ret %d\n", ndev->priv->dpm_clk_tbl[dpm_level].hclk, ret); + return ret; } ndev->hclk_freq = freq; ndev->dpm_level = dpm_level; -- cgit v1.2.3-59-g8ed1b From 1854df7087be70ad54e24b2e308d7558ebea9f27 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 17 Dec 2024 14:17:07 -0600 Subject: drm/rockchip: Don't change hdmi reference clock rate The code that changes hdmi->ref_clk was accidentally copied from downstream code that sets a different clock. We don't actually want to set any clock here at all. Setting this clock incorrectly leads to incorrect timings for DDC, CEC, and HDCP signal generation. No Fixes listed, as the theoretical timing error in DDC appears to still be within tolerances and harmless - and HDCP and CEC are not yet supported. Signed-off-by: Derek Foreman Reviewed-by: Cristian Ciocaltea Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20241217201708.3320673-1-derek.foreman@collabora.com --- drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c index 9916843a6ff3..f41151d49fca 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c @@ -89,7 +89,6 @@ struct rockchip_hdmi_qp { struct regmap *regmap; struct regmap *vo_regmap; struct rockchip_encoder encoder; - struct clk *ref_clk; struct dw_hdmi_qp *hdmi; struct phy *phy; struct gpio_desc *enable_gpio; @@ -122,7 +121,6 @@ static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder) if (crtc && crtc->state) { rate = drm_hdmi_compute_mode_clock(&crtc->state->adjusted_mode, 8, HDMI_COLORSPACE_RGB); - clk_set_rate(hdmi->ref_clk, rate); /* * FIXME: Temporary workaround to pass pixel clock rate * to the PHY driver until phy_configure_opts_hdmi @@ -515,17 +513,6 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, return ret; } - for (i = 0; i < ret; i++) { - if (!strcmp(clks[i].id, "ref")) { - hdmi->ref_clk = clks[1].clk; - break; - } - } - if (!hdmi->ref_clk) { - drm_err(hdmi, "Missing ref clock\n"); - return -EINVAL; - } - hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(hdmi->enable_gpio)) { -- cgit v1.2.3-59-g8ed1b From 9ef80eec5fab5dd840687f55a79c109777b2adf2 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Thu, 2 Jan 2025 16:36:18 +0530 Subject: drm/i915/selftest: Change throttle criteria for rps Current live_rps_control() implementation errors out on throttling. This was done with the assumption that throttling to minimum frequency is a catastrophic failure, which is incorrect. Throttling can happen due to variety of reasons and often times out of our control. Also, the resulting frequency can be at any given point below the maximum allowed. Change throttle criteria to reflect this logic and drop the error, as it doesn't necessarily mean selftest failure. Signed-off-by: Raag Jadav Reviewed-by: Vinay Belgaumkar Reviewed-by: Andi Shyti Acked-by: Rodrigo Vivi Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20250102110618.174415-1-raag.jadav@intel.com --- drivers/gpu/drm/i915/gt/selftest_rps.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index c207a4fb03bf..2d342bd61a31 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -477,12 +477,13 @@ int live_rps_control(void *arg) limit, intel_gpu_freq(rps, limit), min, max, ktime_to_ns(min_dt), ktime_to_ns(max_dt)); - if (limit == rps->min_freq) { - pr_err("%s: GPU throttled to minimum!\n", - engine->name); + if (limit != rps->max_freq) { + u32 throttle = intel_uncore_read(gt->uncore, + intel_gt_perf_limit_reasons_reg(gt)); + + pr_warn("%s: GPU throttled with reasons 0x%08x\n", + engine->name, throttle & GT0_PERF_LIMIT_REASONS_MASK); show_pstate_limits(rps); - err = -ENODEV; - break; } if (igt_flush_test(gt->i915)) { -- cgit v1.2.3-59-g8ed1b From d995dc60e0e9611cc11dc869b176c66dc16b7245 Mon Sep 17 00:00:00 2001 From: Florent Tomasin Date: Tue, 7 Jan 2025 17:33:09 +0000 Subject: drm/panthor: Remove dead code Remove unused function declaration in panthor_gem.h: - `panthor_gem_prime_import_sg_table()` Remove duplicate macro definitions: - `MAX_CSG_PRIO` - `MIN_CS_PER_CSG` - `MIN_CSGS` Signed-off-by: Florent Tomasin Reviewed-by: Boris Brezillon Reviewed-by: Steven Price Signed-off-by: Steven Price Link: https://patchwork.freedesktop.org/patch/msgid/20250107173310.88329-1-florent.tomasin@arm.com --- drivers/gpu/drm/panthor/panthor_fw.c | 1 - drivers/gpu/drm/panthor/panthor_gem.h | 5 ----- drivers/gpu/drm/panthor/panthor_sched.c | 3 --- 3 files changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c index 68eb4fb4d3a8..4a9c4afa9ad7 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.c +++ b/drivers/gpu/drm/panthor/panthor_fw.c @@ -201,7 +201,6 @@ struct panthor_fw_section { #define MIN_CS_PER_CSG 8 #define MIN_CSGS 3 -#define MAX_CSG_PRIO 0xf #define CSF_IFACE_VERSION(major, minor, patch) \ (((major) << 24) | ((minor) << 16) | (patch)) diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h index e43021cf6d45..5749ef2ebe03 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.h +++ b/drivers/gpu/drm/panthor/panthor_gem.h @@ -85,11 +85,6 @@ struct panthor_gem_object *to_panthor_bo(struct drm_gem_object *obj) struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size); -struct drm_gem_object * -panthor_gem_prime_import_sg_table(struct drm_device *ddev, - struct dma_buf_attachment *attach, - struct sg_table *sgt); - int panthor_gem_create_with_handle(struct drm_file *file, struct drm_device *ddev, diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index 77b184c3fb0c..5844a7f639e0 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -88,9 +88,6 @@ #define JOB_TIMEOUT_MS 5000 -#define MIN_CS_PER_CSG 8 - -#define MIN_CSGS 3 #define MAX_CSG_PRIO 0xf #define NUM_INSTRS_PER_CACHE_LINE (64 / sizeof(u64)) -- cgit v1.2.3-59-g8ed1b From 9104ee0868ff0a944f9f7f5ac30bfa88eecaa289 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 10 Jan 2025 22:28:32 -0800 Subject: drm/panthor: fix all mmu kernel-doc comments Use the correct format for all kernel-doc comments. Use structname.membername for named structs. Don't precede function names in kernel-doc with '@' sign. Use the correct function parameter names in kernel-doc comments. This fixes around 80 kernel-doc warnings. Signed-off-by: Randy Dunlap Cc: Boris Brezillon Cc: Steven Price Cc: Liviu Dudau Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Simona Vetter Reviewed-by: Steven Price Signed-off-by: Steven Price Link: https://patchwork.freedesktop.org/patch/msgid/20250111062832.910495-1-rdunlap@infradead.org --- drivers/gpu/drm/panthor/panthor_mmu.c | 71 ++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c index c39e3eb1c15d..5ce80e2532d5 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -53,26 +53,27 @@ struct panthor_mmu { /** @irq: The MMU irq. */ struct panthor_irq irq; - /** @as: Address space related fields. + /** + * @as: Address space related fields. * * The GPU has a limited number of address spaces (AS) slots, forcing * us to re-assign them to re-assign slots on-demand. */ struct { - /** @slots_lock: Lock protecting access to all other AS fields. */ + /** @as.slots_lock: Lock protecting access to all other AS fields. */ struct mutex slots_lock; - /** @alloc_mask: Bitmask encoding the allocated slots. */ + /** @as.alloc_mask: Bitmask encoding the allocated slots. */ unsigned long alloc_mask; - /** @faulty_mask: Bitmask encoding the faulty slots. */ + /** @as.faulty_mask: Bitmask encoding the faulty slots. */ unsigned long faulty_mask; - /** @slots: VMs currently bound to the AS slots. */ + /** @as.slots: VMs currently bound to the AS slots. */ struct panthor_as_slot slots[MAX_AS_SLOTS]; /** - * @lru_list: List of least recently used VMs. + * @as.lru_list: List of least recently used VMs. * * We use this list to pick a VM to evict when all slots are * used. @@ -87,16 +88,16 @@ struct panthor_mmu { /** @vm: VMs management fields */ struct { - /** @lock: Lock protecting access to list. */ + /** @vm.lock: Lock protecting access to list. */ struct mutex lock; - /** @list: List containing all VMs. */ + /** @vm.list: List containing all VMs. */ struct list_head list; - /** @reset_in_progress: True if a reset is in progress. */ + /** @vm.reset_in_progress: True if a reset is in progress. */ bool reset_in_progress; - /** @wq: Workqueue used for the VM_BIND queues. */ + /** @vm.wq: Workqueue used for the VM_BIND queues. */ struct workqueue_struct *wq; } vm; }; @@ -143,14 +144,14 @@ struct panthor_vma { struct panthor_vm_op_ctx { /** @rsvd_page_tables: Pages reserved for the MMU page table update. */ struct { - /** @count: Number of pages reserved. */ + /** @rsvd_page_tables.count: Number of pages reserved. */ u32 count; - /** @ptr: Point to the first unused page in the @pages table. */ + /** @rsvd_page_tables.ptr: Point to the first unused page in the @pages table. */ u32 ptr; /** - * @page: Array of pages that can be used for an MMU page table update. + * @rsvd_page_tables.pages: Array of pages to be used for an MMU page table update. * * After an VM operation, there might be free pages left in this array. * They should be returned to the pt_cache as part of the op_ctx cleanup. @@ -172,10 +173,10 @@ struct panthor_vm_op_ctx { /** @va: Virtual range targeted by the VM operation. */ struct { - /** @addr: Start address. */ + /** @va.addr: Start address. */ u64 addr; - /** @range: Range size. */ + /** @va.range: Range size. */ u64 range; } va; @@ -195,14 +196,14 @@ struct panthor_vm_op_ctx { /** @map: Fields specific to a map operation. */ struct { - /** @vm_bo: Buffer object to map. */ + /** @map.vm_bo: Buffer object to map. */ struct drm_gpuvm_bo *vm_bo; - /** @bo_offset: Offset in the buffer object. */ + /** @map.bo_offset: Offset in the buffer object. */ u64 bo_offset; /** - * @sgt: sg-table pointing to pages backing the GEM object. + * @map.sgt: sg-table pointing to pages backing the GEM object. * * This is gathered at job creation time, such that we don't have * to allocate in ::run_job(). @@ -210,7 +211,7 @@ struct panthor_vm_op_ctx { struct sg_table *sgt; /** - * @new_vma: The new VMA object that will be inserted to the VA tree. + * @map.new_vma: The new VMA object that will be inserted to the VA tree. */ struct panthor_vma *new_vma; } map; @@ -304,27 +305,27 @@ struct panthor_vm { /** @kernel_auto_va: Automatic VA-range for kernel BOs. */ struct { - /** @start: Start of the automatic VA-range for kernel BOs. */ + /** @kernel_auto_va.start: Start of the automatic VA-range for kernel BOs. */ u64 start; - /** @size: Size of the automatic VA-range for kernel BOs. */ + /** @kernel_auto_va.size: Size of the automatic VA-range for kernel BOs. */ u64 end; } kernel_auto_va; /** @as: Address space related fields. */ struct { /** - * @id: ID of the address space this VM is bound to. + * @as.id: ID of the address space this VM is bound to. * * A value of -1 means the VM is inactive/not bound. */ int id; - /** @active_cnt: Number of active users of this VM. */ + /** @as.active_cnt: Number of active users of this VM. */ refcount_t active_cnt; /** - * @lru_node: Used to instead the VM in the panthor_mmu::as::lru_list. + * @as.lru_node: Used to instead the VM in the panthor_mmu::as::lru_list. * * Active VMs should not be inserted in the LRU list. */ @@ -336,13 +337,13 @@ struct panthor_vm { */ struct { /** - * @pool: The heap pool attached to this VM. + * @heaps.pool: The heap pool attached to this VM. * * Will stay NULL until someone creates a heap context on this VM. */ struct panthor_heap_pool *pool; - /** @lock: Lock used to protect access to @pool. */ + /** @heaps.lock: Lock used to protect access to @pool. */ struct mutex lock; } heaps; @@ -408,7 +409,7 @@ struct panthor_vm_bind_job { struct panthor_vm_op_ctx ctx; }; -/** +/* * @pt_cache: Cache used to allocate MMU page tables. * * The pre-allocation pattern forces us to over-allocate to plan for @@ -478,7 +479,7 @@ static void *alloc_pt(void *cookie, size_t size, gfp_t gfp) } /** - * @free_pt() - Custom page table free function + * free_pt() - Custom page table free function * @cookie: Cookie passed at page table allocation time. * @data: Page table to free. * @size: Size of the page table. This size should be fixed, @@ -697,7 +698,7 @@ static void panthor_vm_release_as_locked(struct panthor_vm *vm) /** * panthor_vm_active() - Flag a VM as active - * @VM: VM to flag as active. + * @vm: VM to flag as active. * * Assigns an address space to a VM so it can be used by the GPU/MCU. * @@ -801,7 +802,7 @@ out_dev_exit: /** * panthor_vm_idle() - Flag a VM idle - * @VM: VM to flag as idle. + * @vm: VM to flag as idle. * * When we know the GPU is done with the VM (no more jobs to process), * we can relinquish the AS slot attached to this VM, if any. @@ -1017,7 +1018,7 @@ static int flags_to_prot(u32 flags) /** * panthor_vm_alloc_va() - Allocate a region in the auto-va space - * @VM: VM to allocate a region on. + * @vm: VM to allocate a region on. * @va: start of the VA range. Can be PANTHOR_VM_KERNEL_AUTO_VA if the user * wants the VA to be automatically allocated from the auto-VA range. * @size: size of the VA range. @@ -1063,7 +1064,7 @@ panthor_vm_alloc_va(struct panthor_vm *vm, u64 va, u64 size, /** * panthor_vm_free_va() - Free a region allocated with panthor_vm_alloc_va() - * @VM: VM to free the region on. + * @vm: VM to free the region on. * @va_node: Memory node representing the region to free. */ void panthor_vm_free_va(struct panthor_vm *vm, struct drm_mm_node *va_node) @@ -1492,9 +1493,9 @@ panthor_vm_create_check_args(const struct panthor_device *ptdev, /** * panthor_vm_pool_create_vm() - Create a VM + * @ptdev: The panthor device * @pool: The VM to create this VM on. - * @kernel_va_start: Start of the region reserved for kernel objects. - * @kernel_va_range: Size of the region reserved for kernel objects. + * @args: VM creation args. * * Return: a positive VM ID on success, a negative error code otherwise. */ @@ -1558,6 +1559,8 @@ static void panthor_vm_destroy(struct panthor_vm *vm) * * The VM resources are freed when the last reference on the VM object is * dropped. + * + * Return: %0 for success, negative errno value for failure */ int panthor_vm_pool_destroy_vm(struct panthor_vm_pool *pool, u32 handle) { -- cgit v1.2.3-59-g8ed1b From 573b73e5ac2ce0d58859eace8218f3a7e9212186 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 10 Jan 2025 11:13:01 +0000 Subject: drm/sched: Delete unused update_job_credits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No driver is using the update_job_credits() schduler vfunc so lets remove it. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Acked-by: Danilo Krummrich Acked-by: Boris Brezillon Acked-by: Matt Coster Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250110111301.76909-1-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/scheduler/sched_main.c | 13 ------------- include/drm/gpu_scheduler.h | 13 ------------- 2 files changed, 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 57da84908752..81d69c2ff6ab 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -64,12 +64,6 @@ * credit limit, the job won't be executed. Instead, the scheduler will wait * until the credit count has decreased enough to not overflow its credit limit. * This implies waiting for previously executed jobs. - * - * Optionally, drivers may register a callback (update_job_credits) provided by - * struct drm_sched_backend_ops to update the job's credits dynamically. The - * scheduler executes this callback every time the scheduler considers a job for - * execution and subsequently checks whether the job fits the scheduler's credit - * limit. */ #include @@ -133,13 +127,6 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched, if (!s_job) return false; - if (sched->ops->update_job_credits) { - s_job->credits = sched->ops->update_job_credits(s_job); - - drm_WARN(sched, !s_job->credits, - "Jobs with zero credits bypass job-flow control.\n"); - } - /* If a job exceeds the credit limit, truncate it to the credit limit * itself to guarantee forward progress. */ diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 95e17504e46a..e2e6af8849c6 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -476,19 +476,6 @@ struct drm_sched_backend_ops { * and it's time to clean it up. */ void (*free_job)(struct drm_sched_job *sched_job); - - /** - * @update_job_credits: Called when the scheduler is considering this - * job for execution. - * - * This callback returns the number of credits the job would take if - * pushed to the hardware. Drivers may use this to dynamically update - * the job's credit count. For instance, deduct the number of credits - * for already signalled native fences. - * - * This callback is optional. - */ - u32 (*update_job_credits)(struct drm_sched_job *sched_job); }; /** -- cgit v1.2.3-59-g8ed1b From 155c77f45f63dd58a37eeb0896b0b140ab785836 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Wed, 11 Dec 2024 12:17:26 +0100 Subject: drm/xe: introduce xe_gt_reset and xe_gt_wait_for_reset Add synchronous version gt reset as there are few places where it is expected. Also add a wait helper to wait until gt reset is done. Signed-off-by: Maciej Patelczyk Reviewed-by: Lucas De Marchi Fixes: f3bc5bb4d53d ("drm/xe: Allow userspace to configure CCS mode") Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20241211111727.1481476-2-maciej.patelczyk@intel.com Signed-off-by: Nirmoy Das --- drivers/gpu/drm/xe/tests/xe_bo.c | 7 +++---- drivers/gpu/drm/xe/tests/xe_mocs.c | 3 +-- drivers/gpu/drm/xe/xe_gt.h | 25 +++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_gt_debugfs.c | 4 +--- 4 files changed, 30 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c index 405ff904153e..6795d1d916e4 100644 --- a/drivers/gpu/drm/xe/tests/xe_bo.c +++ b/drivers/gpu/drm/xe/tests/xe_bo.c @@ -264,10 +264,9 @@ static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struc * however seems quite fragile not to also restart the GT. Try * to do that here by triggering a GT reset. */ - for_each_gt(__gt, xe, id) { - xe_gt_reset_async(__gt); - flush_work(&__gt->reset.worker); - } + for_each_gt(__gt, xe, id) + xe_gt_reset(__gt); + if (err) { KUNIT_FAIL(test, "restore kernel err=%pe\n", ERR_PTR(err)); diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c index d3f71d13eb81..ef1e5256c56a 100644 --- a/drivers/gpu/drm/xe/tests/xe_mocs.c +++ b/drivers/gpu/drm/xe/tests/xe_mocs.c @@ -162,8 +162,7 @@ static int mocs_reset_test_run_device(struct xe_device *xe) if (flags & HAS_LNCF_MOCS) read_l3cc_table(gt, &mocs.table); - xe_gt_reset_async(gt); - flush_work(>->reset.worker); + xe_gt_reset(gt); kunit_info(test, "mocs_reset_test after reset\n"); if (flags & HAS_GLOBAL_MOCS) diff --git a/drivers/gpu/drm/xe/xe_gt.h b/drivers/gpu/drm/xe/xe_gt.h index 4e4e8e103419..e504cc33ade4 100644 --- a/drivers/gpu/drm/xe/xe_gt.h +++ b/drivers/gpu/drm/xe/xe_gt.h @@ -56,6 +56,31 @@ void xe_gt_sanitize(struct xe_gt *gt); int xe_gt_sanitize_freq(struct xe_gt *gt); void xe_gt_remove(struct xe_gt *gt); +/** + * xe_gt_wait_for_reset - wait for gt's async reset to finalize. + * @gt: GT structure + * Return: + * %true if it waited for the work to finish execution, + * %false if there was no scheduled reset or it was done. + */ +static inline bool xe_gt_wait_for_reset(struct xe_gt *gt) +{ + return flush_work(>->reset.worker); +} + +/** + * xe_gt_reset - perform synchronous reset + * @gt: GT structure + * Return: + * %true if it waited for the reset to finish, + * %false if there was no scheduled reset. + */ +static inline bool xe_gt_reset(struct xe_gt *gt) +{ + xe_gt_reset_async(gt); + return xe_gt_wait_for_reset(gt); +} + /** * xe_gt_any_hw_engine_by_reset_domain - scan the list of engines and return the * first that matches the same reset domain as @class diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c index 3e8c351a0eab..e7792858b1e4 100644 --- a/drivers/gpu/drm/xe/xe_gt_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c @@ -132,11 +132,9 @@ static int force_reset(struct xe_gt *gt, struct drm_printer *p) static int force_reset_sync(struct xe_gt *gt, struct drm_printer *p) { xe_pm_runtime_get(gt_to_xe(gt)); - xe_gt_reset_async(gt); + xe_gt_reset(gt); xe_pm_runtime_put(gt_to_xe(gt)); - flush_work(>->reset.worker); - return 0; } -- cgit v1.2.3-59-g8ed1b From 480fb9806e2e073532f7786166287114c696b340 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Wed, 11 Dec 2024 12:17:27 +0100 Subject: drm/xe: make change ccs_mode a synchronous action If ccs_mode is being modified via /sys/class/drm/cardX/device/tileY/gtY/ccs_mode the asynchronous reset is triggered and the write returns immediately. With that some test receive false information about number of CCS engines or even fail if they proceed without delay after changing the ccs_mode. Changing the ccs_mode change from async to sync to prevent failures in tests. Signed-off-by: Maciej Patelczyk Reviewed-by: Lucas De Marchi Fixes: f3bc5bb4d53d ("drm/xe: Allow userspace to configure CCS mode") Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20241211111727.1481476-3-maciej.patelczyk@intel.com Signed-off-by: Nirmoy Das --- drivers/gpu/drm/xe/xe_gt_ccs_mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_ccs_mode.c b/drivers/gpu/drm/xe/xe_gt_ccs_mode.c index b6adfb9f2030..50fffc9ebf62 100644 --- a/drivers/gpu/drm/xe/xe_gt_ccs_mode.c +++ b/drivers/gpu/drm/xe/xe_gt_ccs_mode.c @@ -150,7 +150,7 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr, xe_gt_info(gt, "Setting compute mode to %d\n", num_engines); gt->ccs_mode = num_engines; xe_gt_record_user_engines(gt); - xe_gt_reset_async(gt); + xe_gt_reset(gt); } mutex_unlock(&xe->drm.filelist_mutex); -- cgit v1.2.3-59-g8ed1b From 92029e0baa5313ba208103f90086f59070bbf93b Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Wed, 8 Jan 2025 15:13:23 +0100 Subject: drm/xe/ptl: Apply Wa_14023061436 Enable WMTP for the BTD kernel to address Wa14023061436 by setting the proper TDL Chicken Bit. v2: Apply it on engine_was[] as this register is not part of LRC(Matt) Apply it for first_render_or_compute in case this gets extended to compute only platforms(Matt). Cc: Gustavo Sousa Cc: Matt Roper Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20250108141323.311601-1-nirmoy.das@intel.com Signed-off-by: Nirmoy Das --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 3 +++ drivers/gpu/drm/xe/xe_wa.c | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 162f18e975da..b4283ac030f4 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -500,6 +500,9 @@ #define LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK REG_GENMASK(13, 11) #define DIS_ATOMIC_CHAINING_TYPED_WRITES REG_BIT(3) +#define TDL_CHICKEN XE_REG_MCR(0xe5f4, XE_REG_OPTION_MASKED) +#define QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE REG_BIT(12) + #define LSC_CHICKEN_BIT_0 XE_REG_MCR(0xe7c8) #define DISABLE_D8_D16_COASLESCE REG_BIT(30) #define WR_REQ_CHAINING_DIS REG_BIT(26) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 570fe0376402..744dba4fdb58 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -613,6 +613,11 @@ static const struct xe_rtp_entry_sr engine_was[] = { XE_RTP_ACTIONS(FIELD_SET(SAMPLER_MODE, SMP_WAIT_FETCH_MERGING_COUNTER, SMP_FORCE_128B_OVERFETCH)) }, + { XE_RTP_NAME("14023061436"), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(TDL_CHICKEN, QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE)) + }, {} }; -- cgit v1.2.3-59-g8ed1b From 57e233c3bd63f32d2c7e937db2e16b98f723ce2f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 17 Dec 2024 10:24:57 +0100 Subject: drm/panthor: Fix a race between the reset and suspend path If a reset is scheduled when the suspend happens, we drop the reset-pending info on the floor assuming the resume will fix things, but the resume logic might try a fast reset. If we're lucky, the fast reset fails and we fallback to a slow reset, but if the FW was corrupted in a way that makes it partially functional (it boots but doesn't quite do what it's expected to do), we won't notice immediately that things are not working correctly, leading to a new reset further down the road. Fixes: 5fe909cae118 ("drm/panthor: Add the device logical block") Signed-off-by: Boris Brezillon Reviewed-by: Liviu Dudau Reviewed-by: Steven Price Signed-off-by: Steven Price Link: https://patchwork.freedesktop.org/patch/msgid/20241217092457.1582053-1-boris.brezillon@collabora.com --- drivers/gpu/drm/panthor/panthor_device.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c index 0a37cfeeb181..a9da1d1eeb70 100644 --- a/drivers/gpu/drm/panthor/panthor_device.c +++ b/drivers/gpu/drm/panthor/panthor_device.c @@ -128,14 +128,11 @@ static void panthor_device_reset_work(struct work_struct *work) struct panthor_device *ptdev = container_of(work, struct panthor_device, reset.work); int ret = 0, cookie; - if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) { - /* - * No need for a reset as the device has been (or will be) - * powered down - */ - atomic_set(&ptdev->reset.pending, 0); + /* If the device is entering suspend, we don't reset. A slow reset will + * be forced at resume time instead. + */ + if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) return; - } if (!drm_dev_enter(&ptdev->base, &cookie)) return; @@ -477,6 +474,14 @@ int panthor_device_resume(struct device *dev) if (panthor_device_is_initialized(ptdev) && drm_dev_enter(&ptdev->base, &cookie)) { + /* If there was a reset pending at the time we suspended the + * device, we force a slow reset. + */ + if (atomic_read(&ptdev->reset.pending)) { + ptdev->reset.fast = false; + atomic_set(&ptdev->reset.pending, 0); + } + ret = panthor_device_resume_hw_components(ptdev); if (ret && ptdev->reset.fast) { drm_err(&ptdev->base, "Fast reset failed, trying a slow reset"); @@ -493,9 +498,6 @@ int panthor_device_resume(struct device *dev) goto err_suspend_devfreq; } - if (atomic_read(&ptdev->reset.pending)) - queue_work(ptdev->reset.wq, &ptdev->reset.work); - /* Clear all IOMEM mappings pointing to this device after we've * resumed. This way the fake mappings pointing to the dummy pages * are removed and the real iomem mapping will be restored on next -- cgit v1.2.3-59-g8ed1b From 1f463794097dcdf4c64fffd31de2177681525e35 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Tue, 17 Dec 2024 15:58:44 +0100 Subject: drm/ttm: Balance ttm_resource_cursor_init() and ttm_resource_cursor_fini() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the interface more symmetric by providing and using a ttm_resource_cursor_init(). v10: - Fix a stray newline (Matthew Brost) - Update kerneldoc (Matthew Brost) Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20241217145852.37342-2-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_bo.c | 3 ++- drivers/gpu/drm/ttm/ttm_bo_util.c | 3 ++- drivers/gpu/drm/ttm/ttm_resource.c | 35 ++++++++++++++++++++++++----------- include/drm/ttm/ttm_resource.h | 11 ++++++----- 4 files changed, 34 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 48c5365efca1..06d6a452c4f4 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -450,7 +450,8 @@ int ttm_bo_evict_first(struct ttm_device *bdev, struct ttm_resource_manager *man int ret = 0; spin_lock(&bdev->lru_lock); - res = ttm_resource_manager_first(man, &cursor); + ttm_resource_cursor_init(&cursor, man); + res = ttm_resource_manager_first(&cursor); ttm_resource_cursor_fini(&cursor); if (!res) { ret = -ENOENT; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index d939925efa81..917096bd5f68 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -865,7 +865,8 @@ s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, struct ttm_device *bdev, s64 lret; spin_lock(&bdev->lru_lock); - ttm_resource_manager_for_each_res(man, &cursor, res) { + ttm_resource_cursor_init(&cursor, man); + ttm_resource_manager_for_each_res(&cursor, res) { struct ttm_buffer_object *bo = res->bo; bool bo_needs_unlock = false; bool bo_locked = false; diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index a87665eb28a6..e19360cc7930 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -81,6 +81,23 @@ static void ttm_bulk_move_drop_cursors(struct ttm_lru_bulk_move *bulk) ttm_resource_cursor_clear_bulk(cursor); } +/** + * ttm_resource_cursor_init() - Initialize a struct ttm_resource_cursor + * @cursor: The cursor to initialize. + * @man: The resource manager. + * + * Initialize the cursor before using it for iteration. + */ +void ttm_resource_cursor_init(struct ttm_resource_cursor *cursor, + struct ttm_resource_manager *man) +{ + cursor->priority = 0; + cursor->man = man; + ttm_lru_item_init(&cursor->hitch, TTM_LRU_HITCH); + INIT_LIST_HEAD(&cursor->bulk_link); + INIT_LIST_HEAD(&cursor->hitch.link); +} + /** * ttm_resource_cursor_fini() - Finalize the LRU list cursor usage * @cursor: The struct ttm_resource_cursor to finalize. @@ -593,7 +610,6 @@ ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor, /** * ttm_resource_manager_first() - Start iterating over the resources * of a resource manager - * @man: resource manager to iterate over * @cursor: cursor to record the position * * Initializes the cursor and starts iterating. When done iterating, @@ -602,17 +618,16 @@ ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor, * Return: The first resource from the resource manager. */ struct ttm_resource * -ttm_resource_manager_first(struct ttm_resource_manager *man, - struct ttm_resource_cursor *cursor) +ttm_resource_manager_first(struct ttm_resource_cursor *cursor) { - lockdep_assert_held(&man->bdev->lru_lock); + struct ttm_resource_manager *man = cursor->man; - cursor->priority = 0; - cursor->man = man; - ttm_lru_item_init(&cursor->hitch, TTM_LRU_HITCH); - INIT_LIST_HEAD(&cursor->bulk_link); - list_add(&cursor->hitch.link, &man->lru[cursor->priority]); + if (WARN_ON_ONCE(!man)) + return NULL; + + lockdep_assert_held(&man->bdev->lru_lock); + list_move(&cursor->hitch.link, &man->lru[cursor->priority]); return ttm_resource_manager_next(cursor); } @@ -648,8 +663,6 @@ ttm_resource_manager_next(struct ttm_resource_cursor *cursor) ttm_resource_cursor_clear_bulk(cursor); } - ttm_resource_cursor_fini(cursor); - return NULL; } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index be034be56ba1..e1f3b95d73b6 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -325,6 +325,9 @@ struct ttm_resource_cursor { unsigned int priority; }; +void ttm_resource_cursor_init(struct ttm_resource_cursor *cursor, + struct ttm_resource_manager *man); + void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor); /** @@ -456,8 +459,7 @@ void ttm_resource_manager_debug(struct ttm_resource_manager *man, struct drm_printer *p); struct ttm_resource * -ttm_resource_manager_first(struct ttm_resource_manager *man, - struct ttm_resource_cursor *cursor); +ttm_resource_manager_first(struct ttm_resource_cursor *cursor); struct ttm_resource * ttm_resource_manager_next(struct ttm_resource_cursor *cursor); @@ -466,14 +468,13 @@ ttm_lru_first_res_or_null(struct list_head *head); /** * ttm_resource_manager_for_each_res - iterate over all resources - * @man: the resource manager * @cursor: struct ttm_resource_cursor for the current position * @res: the current resource * * Iterate over all the evictable resources in a resource manager. */ -#define ttm_resource_manager_for_each_res(man, cursor, res) \ - for (res = ttm_resource_manager_first(man, cursor); res; \ +#define ttm_resource_manager_for_each_res(cursor, res) \ + for (res = ttm_resource_manager_first(cursor); res; \ res = ttm_resource_manager_next(cursor)) struct ttm_kmap_iter * -- cgit v1.2.3-59-g8ed1b From 1d3160c7cba37b48be453f29ec2faede77002d14 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Tue, 17 Dec 2024 15:58:46 +0100 Subject: drm/ttm/pool: Restructure the pool allocation code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the pool allocation code somewhat by merging loop arguments used by multiple functions together in a struct and simplifying the loop. Also add documentation. This hopefully makes the behaviour of the allocation loop simplier to understand, but above all paves the way for upcoming restore-while-allocating functionality. There are no functional changes, but the "allow_pools" bool introduced to keep current functionality could be removed as a follow up, which would enable using write-back cached pools when allocating memory for other caching modes, rather than to resort to allocating from the system directly. v15: - Introduce this patch to simplify the upcoming patch that introduces restore while allocating. Signed-off-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20241217145852.37342-4-thomas.hellstrom@linux.intel.com Reviewed-by: Christian König Reviewed-by: Matthew Brost Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_pool.c | 183 ++++++++++++++++++++++++----------------- 1 file changed, 108 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index 8504dbe19c1a..c9eba76d5143 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -58,6 +58,23 @@ struct ttm_pool_dma { unsigned long vaddr; }; +/** + * struct ttm_pool_alloc_state - Current state of the tt page allocation process + * @pages: Pointer to the next tt page pointer to populate. + * @caching_divide: Pointer to the first page pointer whose page has a staged but + * not committed caching transition from write-back to @tt_caching. + * @dma_addr: Pointer to the next tt dma_address entry to populate if any. + * @remaining_pages: Remaining pages to populate. + * @tt_caching: The requested cpu-caching for the pages allocated. + */ +struct ttm_pool_alloc_state { + struct page **pages; + struct page **caching_divide; + dma_addr_t *dma_addr; + pgoff_t remaining_pages; + enum ttm_caching tt_caching; +}; + static unsigned long page_pool_size; MODULE_PARM_DESC(page_pool_size, "Number of pages in the WC/UC/DMA pool"); @@ -160,25 +177,25 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching, kfree(dma); } -/* Apply a new caching to an array of pages */ -static int ttm_pool_apply_caching(struct page **first, struct page **last, - enum ttm_caching caching) +/* Apply any cpu-caching deferred during page allocation */ +static int ttm_pool_apply_caching(struct ttm_pool_alloc_state *alloc) { #ifdef CONFIG_X86 - unsigned int num_pages = last - first; + unsigned int num_pages = alloc->pages - alloc->caching_divide; if (!num_pages) return 0; - switch (caching) { + switch (alloc->tt_caching) { case ttm_cached: break; case ttm_write_combined: - return set_pages_array_wc(first, num_pages); + return set_pages_array_wc(alloc->caching_divide, num_pages); case ttm_uncached: - return set_pages_array_uc(first, num_pages); + return set_pages_array_uc(alloc->caching_divide, num_pages); } #endif + alloc->caching_divide = alloc->pages; return 0; } @@ -354,24 +371,41 @@ static unsigned int ttm_pool_page_order(struct ttm_pool *pool, struct page *p) return p->private; } -/* Called when we got a page, either from a pool or newly allocated */ +/* + * Called when we got a page, either from a pool or newly allocated. + * if needed, dma map the page and populate the dma address array. + * Populate the page address array. + * If the caching is consistent, update any deferred caching. Otherwise + * stage this page for an upcoming deferred caching update. + */ static int ttm_pool_page_allocated(struct ttm_pool *pool, unsigned int order, - struct page *p, dma_addr_t **dma_addr, - unsigned long *num_pages, - struct page ***pages) + struct page *p, enum ttm_caching page_caching, + struct ttm_pool_alloc_state *alloc) { - unsigned int i; - int r; + pgoff_t i, nr = 1UL << order; + bool caching_consistent; + int r = 0; + + caching_consistent = (page_caching == alloc->tt_caching) || PageHighMem(p); + + if (caching_consistent) { + r = ttm_pool_apply_caching(alloc); + if (r) + return r; + } - if (*dma_addr) { - r = ttm_pool_map(pool, order, p, dma_addr); + if (alloc->dma_addr) { + r = ttm_pool_map(pool, order, p, &alloc->dma_addr); if (r) return r; } - *num_pages -= 1 << order; - for (i = 1 << order; i; --i, ++(*pages), ++p) - **pages = p; + alloc->remaining_pages -= nr; + for (i = 0; i < nr; ++i) + *alloc->pages++ = p++; + + if (caching_consistent) + alloc->caching_divide = alloc->pages; return 0; } @@ -413,6 +447,26 @@ static void ttm_pool_free_range(struct ttm_pool *pool, struct ttm_tt *tt, } } +static void ttm_pool_alloc_state_init(const struct ttm_tt *tt, + struct ttm_pool_alloc_state *alloc) +{ + alloc->pages = tt->pages; + alloc->caching_divide = tt->pages; + alloc->dma_addr = tt->dma_address; + alloc->remaining_pages = tt->num_pages; + alloc->tt_caching = tt->caching; +} + +/* + * Find a suitable allocation order based on highest desired order + * and number of remaining pages + */ +static unsigned int ttm_pool_alloc_find_order(unsigned int highest, + const struct ttm_pool_alloc_state *alloc) +{ + return min_t(unsigned int, highest, __fls(alloc->remaining_pages)); +} + /** * ttm_pool_alloc - Fill a ttm_tt object * @@ -428,19 +482,19 @@ static void ttm_pool_free_range(struct ttm_pool *pool, struct ttm_tt *tt, int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt, struct ttm_operation_ctx *ctx) { - pgoff_t num_pages = tt->num_pages; - dma_addr_t *dma_addr = tt->dma_address; - struct page **caching = tt->pages; - struct page **pages = tt->pages; + struct ttm_pool_alloc_state alloc; enum ttm_caching page_caching; gfp_t gfp_flags = GFP_USER; pgoff_t caching_divide; unsigned int order; + bool allow_pools; struct page *p; int r; - WARN_ON(!num_pages || ttm_tt_is_populated(tt)); - WARN_ON(dma_addr && !pool->dev); + ttm_pool_alloc_state_init(tt, &alloc); + + WARN_ON(!alloc.remaining_pages || ttm_tt_is_populated(tt)); + WARN_ON(alloc.dma_addr && !pool->dev); if (tt->page_flags & TTM_TT_FLAG_ZERO_ALLOC) gfp_flags |= __GFP_ZERO; @@ -453,67 +507,46 @@ int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt, else gfp_flags |= GFP_HIGHUSER; - for (order = min_t(unsigned int, MAX_PAGE_ORDER, __fls(num_pages)); - num_pages; - order = min_t(unsigned int, order, __fls(num_pages))) { + page_caching = tt->caching; + allow_pools = true; + for (order = ttm_pool_alloc_find_order(MAX_PAGE_ORDER, &alloc); + alloc.remaining_pages; + order = ttm_pool_alloc_find_order(order, &alloc)) { struct ttm_pool_type *pt; - page_caching = tt->caching; - pt = ttm_pool_select_type(pool, tt->caching, order); - p = pt ? ttm_pool_type_take(pt) : NULL; - if (p) { - r = ttm_pool_apply_caching(caching, pages, - tt->caching); - if (r) - goto error_free_page; - - caching = pages; - do { - r = ttm_pool_page_allocated(pool, order, p, - &dma_addr, - &num_pages, - &pages); - if (r) - goto error_free_page; - - caching = pages; - if (num_pages < (1 << order)) - break; - - p = ttm_pool_type_take(pt); - } while (p); - } - - page_caching = ttm_cached; - while (num_pages >= (1 << order) && - (p = ttm_pool_alloc_page(pool, gfp_flags, order))) { - - if (PageHighMem(p)) { - r = ttm_pool_apply_caching(caching, pages, - tt->caching); - if (r) - goto error_free_page; - caching = pages; - } - r = ttm_pool_page_allocated(pool, order, p, &dma_addr, - &num_pages, &pages); - if (r) - goto error_free_page; - if (PageHighMem(p)) - caching = pages; + /* First, try to allocate a page from a pool if one exists. */ + p = NULL; + pt = ttm_pool_select_type(pool, page_caching, order); + if (pt && allow_pools) + p = ttm_pool_type_take(pt); + /* + * If that fails or previously failed, allocate from system. + * Note that this also disallows additional pool allocations using + * write-back cached pools of the same order. Consider removing + * that behaviour. + */ + if (!p) { + page_caching = ttm_cached; + allow_pools = false; + p = ttm_pool_alloc_page(pool, gfp_flags, order); } - + /* If that fails, lower the order if possible and retry. */ if (!p) { if (order) { --order; + page_caching = tt->caching; + allow_pools = true; continue; } r = -ENOMEM; goto error_free_all; } + r = ttm_pool_page_allocated(pool, order, p, page_caching, &alloc); + if (r) + goto error_free_page; } - r = ttm_pool_apply_caching(caching, pages, tt->caching); + r = ttm_pool_apply_caching(&alloc); if (r) goto error_free_all; @@ -523,10 +556,10 @@ error_free_page: ttm_pool_free_page(pool, page_caching, order, p); error_free_all: - num_pages = tt->num_pages - num_pages; - caching_divide = caching - tt->pages; + caching_divide = alloc.caching_divide - tt->pages; ttm_pool_free_range(pool, tt, tt->caching, 0, caching_divide); - ttm_pool_free_range(pool, tt, ttm_cached, caching_divide, num_pages); + ttm_pool_free_range(pool, tt, ttm_cached, caching_divide, + tt->num_pages - alloc.remaining_pages); return r; } -- cgit v1.2.3-59-g8ed1b From 0d6c9edf9e5b25361bb23a151ad162878ecd81a5 Mon Sep 17 00:00:00 2001 From: Tejas Vipin Date: Mon, 6 Jan 2025 09:41:29 +0530 Subject: drm/panel: ebbg-ft8719: transition to mipi_dsi wrapped functions Changes the ebbg-ft8719 panel to use multi style functions for improved error handling. Signed-off-by: Tejas Vipin Reviewed-by: Neil Armstrong Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250106041129.114867-1-tejasvipin76@gmail.com --- drivers/gpu/drm/panel/panel-ebbg-ft8719.c | 67 ++++++++----------------------- 1 file changed, 16 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c index e85d63a176d0..0bfed0ec0bbc 100644 --- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c +++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c @@ -57,65 +57,39 @@ static void ebbg_ft8719_reset(struct ebbg_ft8719 *ctx) static int ebbg_ft8719_on(struct ebbg_ft8719 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00ff); - if (ret < 0) { - dev_err(dev, "Failed to set display brightness: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x00ff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 90); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(90); - - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } - - return 0; + return dsi_ctx.accum_err; } static int ebbg_ft8719_off(struct ebbg_ft8719 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - usleep_range(10000, 11000); - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(90); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 10000, 11000); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 90); - return 0; + return dsi_ctx.accum_err; } static int ebbg_ft8719_prepare(struct drm_panel *panel) { struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -126,7 +100,6 @@ static int ebbg_ft8719_prepare(struct drm_panel *panel) ret = ebbg_ft8719_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 1); return ret; } @@ -137,18 +110,10 @@ static int ebbg_ft8719_prepare(struct drm_panel *panel) static int ebbg_ft8719_unprepare(struct drm_panel *panel) { struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - - ret = ebbg_ft8719_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + ebbg_ft8719_off(ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 1); - - ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret) - dev_err(panel->dev, "Failed to disable regulators: %d\n", ret); + regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); return 0; } -- cgit v1.2.3-59-g8ed1b From 8025f23728e9bc817495d48a04954cdee27462bd Mon Sep 17 00:00:00 2001 From: Tejas Vipin Date: Tue, 7 Jan 2025 14:55:10 +0530 Subject: drm/panel: xinpeng-xpp055c272: transition to mipi_dsi wrapped functions Changes the xinpeng-xpp055c272 panel to use multi style functions for improved error handling. Reviewed-by: Neil Armstrong Signed-off-by: Tejas Vipin Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250107092510.174089-1-tejasvipin76@gmail.com --- drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c | 178 ++++++++++------------- 1 file changed, 80 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c index 22a14006765e..2b91414c2829 100644 --- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c +++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c @@ -59,91 +59,80 @@ static inline struct xpp055c272 *panel_to_xpp055c272(struct drm_panel *panel) return container_of(panel, struct xpp055c272, panel); } -static int xpp055c272_init_sequence(struct xpp055c272 *ctx) +static void xpp055c272_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - struct device *dev = ctx->dev; - /* * Init sequence was supplied by the panel vendor without much * documentation. */ - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETMIPI, - 0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25, - 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01, - 0x00, 0x00, 0x37); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER_EXT, 0x25); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETRGBIF, - 0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00, - 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETSCR, - 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, - 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVDC, 0x46); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPANEL, 0x0b); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETCYC, 0x80); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEQ, - 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER, - 0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd, - 0x67, 0x77, 0x33, 0x33); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff, - 0xff, 0x01, 0xff); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETBGP, 0x09, 0x09); - msleep(20); - - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVCOM, 0x87, 0x95); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP1, - 0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12, - 0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18, - 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42, - 0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58, - 0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88, - 0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP2, - 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35, - 0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f, - 0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88, - 0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05, - 0xa0, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGAMMA, - 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36, - 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11, - 0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, - 0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, - 0x11, 0x18); - - msleep(60); - - dev_dbg(dev, "Panel init sequence done\n"); - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETMIPI, + 0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25, + 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01, + 0x00, 0x00, 0x37); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPOWER_EXT, 0x25); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETRGBIF, + 0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETSCR, + 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, + 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETVDC, 0x46); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPANEL, 0x0b); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETCYC, 0x80); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETEQ, + 0x07, 0x07, 0x0b, 0x0b, 0x03, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xC0, 0x10); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETPOWER, + 0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd, + 0x67, 0x77, 0x33, 0x33); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff, + 0xff, 0x01, 0xff); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETBGP, 0x09, 0x09); + mipi_dsi_msleep(dsi_ctx, 20); + + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETVCOM, 0x87, 0x95); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETGIP1, + 0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12, + 0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42, + 0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58, + 0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88, + 0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETGIP2, + 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35, + 0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f, + 0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88, + 0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05, + 0xa0, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, XPP055C272_CMD_SETGAMMA, + 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36, + 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11, + 0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, + 0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, + 0x11, 0x18); + + mipi_dsi_msleep(dsi_ctx, 60); } static int xpp055c272_unprepare(struct drm_panel *panel) { struct xpp055c272 *ctx = panel_to_xpp055c272(panel); struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) - dev_err(ctx->dev, "failed to set display off: %d\n", ret); - - mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(ctx->dev, "failed to enter sleep mode: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + if (dsi_ctx.accum_err) + return dsi_ctx.accum_err; regulator_disable(ctx->iovcc); regulator_disable(ctx->vci); @@ -155,17 +144,19 @@ static int xpp055c272_prepare(struct drm_panel *panel) { struct xpp055c272 *ctx = panel_to_xpp055c272(panel); struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dev_dbg(ctx->dev, "Resetting the panel\n"); - ret = regulator_enable(ctx->vci); - if (ret < 0) { - dev_err(ctx->dev, "Failed to enable vci supply: %d\n", ret); - return ret; + dsi_ctx.accum_err = regulator_enable(ctx->vci); + if (dsi_ctx.accum_err) { + dev_err(ctx->dev, "Failed to enable vci supply: %d\n", + dsi_ctx.accum_err); + return dsi_ctx.accum_err; } - ret = regulator_enable(ctx->iovcc); - if (ret < 0) { - dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); + dsi_ctx.accum_err = regulator_enable(ctx->iovcc); + if (dsi_ctx.accum_err) { + dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", + dsi_ctx.accum_err); goto disable_vci; } @@ -177,26 +168,17 @@ static int xpp055c272_prepare(struct drm_panel *panel) /* T8: 20ms */ msleep(20); - ret = xpp055c272_init_sequence(ctx); - if (ret < 0) { - dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); - goto disable_iovcc; - } - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); - goto disable_iovcc; - } + xpp055c272_init_sequence(&dsi_ctx); + if (!dsi_ctx.accum_err) + dev_dbg(ctx->dev, "Panel init sequence done\n"); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); /* T9: 120ms */ - msleep(120); + mipi_dsi_msleep(&dsi_ctx, 120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(ctx->dev, "Failed to set display on: %d\n", ret); + if (dsi_ctx.accum_err) goto disable_iovcc; - } msleep(50); @@ -206,7 +188,7 @@ disable_iovcc: regulator_disable(ctx->iovcc); disable_vci: regulator_disable(ctx->vci); - return ret; + return dsi_ctx.accum_err; } static const struct drm_display_mode default_mode = { -- cgit v1.2.3-59-g8ed1b From 57af0c0f3b3bad8669dbcdb6b1d31b1537c614ad Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Sun, 22 Dec 2024 00:20:41 +0000 Subject: drm/i915/gvt: Remove intel_gvt_ggtt_h2g<->index intel_gvt_ggtt_h2g_index() and intel_gvt_ggtt_index_g2h() were added in 2016 by commit 2707e4446688 ("drm/i915/gvt: vGPU graphics memory virtualization") but haven't been used. Remove them. They were the only users of intel_gvt_ggtt_gmadr_g2h() and intel_gvt_ggtt_gmadr_h2g(). Remove them. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Zhenyu Wang Link: https://patchwork.freedesktop.org/patch/msgid/20241222002043.173080-2-linux@treblig.org Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/gtt.c | 66 ------------------------------------------ drivers/gpu/drm/i915/gvt/gvt.h | 6 ---- 2 files changed, 72 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 1bce1493b86f..464fb17e82ee 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -71,72 +71,6 @@ bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size) return false; } -/* translate a guest gmadr to host gmadr */ -int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr) -{ - struct drm_i915_private *i915 = vgpu->gvt->gt->i915; - - if (drm_WARN(&i915->drm, !vgpu_gmadr_is_valid(vgpu, g_addr), - "invalid guest gmadr %llx\n", g_addr)) - return -EACCES; - - if (vgpu_gmadr_is_aperture(vgpu, g_addr)) - *h_addr = vgpu_aperture_gmadr_base(vgpu) - + (g_addr - vgpu_aperture_offset(vgpu)); - else - *h_addr = vgpu_hidden_gmadr_base(vgpu) - + (g_addr - vgpu_hidden_offset(vgpu)); - return 0; -} - -/* translate a host gmadr to guest gmadr */ -int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr) -{ - struct drm_i915_private *i915 = vgpu->gvt->gt->i915; - - if (drm_WARN(&i915->drm, !gvt_gmadr_is_valid(vgpu->gvt, h_addr), - "invalid host gmadr %llx\n", h_addr)) - return -EACCES; - - if (gvt_gmadr_is_aperture(vgpu->gvt, h_addr)) - *g_addr = vgpu_aperture_gmadr_base(vgpu) - + (h_addr - gvt_aperture_gmadr_base(vgpu->gvt)); - else - *g_addr = vgpu_hidden_gmadr_base(vgpu) - + (h_addr - gvt_hidden_gmadr_base(vgpu->gvt)); - return 0; -} - -int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, - unsigned long *h_index) -{ - u64 h_addr; - int ret; - - ret = intel_gvt_ggtt_gmadr_g2h(vgpu, g_index << I915_GTT_PAGE_SHIFT, - &h_addr); - if (ret) - return ret; - - *h_index = h_addr >> I915_GTT_PAGE_SHIFT; - return 0; -} - -int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, - unsigned long *g_index) -{ - u64 g_addr; - int ret; - - ret = intel_gvt_ggtt_gmadr_h2g(vgpu, h_index << I915_GTT_PAGE_SHIFT, - &g_addr); - if (ret) - return ret; - - *g_index = g_addr >> I915_GTT_PAGE_SHIFT; - return 0; -} - #define gtt_type_is_entry(type) \ (type > GTT_TYPE_INVALID && type < GTT_TYPE_PPGTT_ENTRY \ && type != GTT_TYPE_PPGTT_PTE_ENTRY \ diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 2c95aeef4e41..8580c6d057e7 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -531,12 +531,6 @@ int intel_gvt_set_edid(struct intel_vgpu *vgpu, int port_num); gvt_gmadr_is_hidden(gvt, gmadr)) bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size); -int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr); -int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr); -int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, - unsigned long *h_index); -int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, - unsigned long *g_index); void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, bool primary); -- cgit v1.2.3-59-g8ed1b From 35bdd1060a04e234e85bb7494d505d2bbdcabd58 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Sun, 22 Dec 2024 00:20:42 +0000 Subject: drm/i915/gvt: Remove unused intel_vgpu_decode_sprite_plane intel_vgpu_decode_sprite_plane() was added in 2017 by commit 9f31d1063b43 ("drm/i915/gvt: Add framebuffer decoder support") but has remained unused. Remove it. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Zhenyu Wang Link: https://patchwork.freedesktop.org/patch/msgid/20241222002043.173080-3-linux@treblig.org Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/fb_decoder.c | 117 ---------------------------------- drivers/gpu/drm/i915/gvt/fb_decoder.h | 2 - 2 files changed, 119 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c index 15cce973e1ae..f9f7ef131371 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.c +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c @@ -398,120 +398,3 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, plane->y_hot = vgpu_vreg_t(vgpu, vgtif_reg(cursor_y_hot)); return 0; } - -#define SPRITE_FORMAT_NUM (1 << 3) - -static const struct pixel_format sprite_pixel_formats[SPRITE_FORMAT_NUM] = { - [0x0] = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"}, - [0x1] = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"}, - [0x2] = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"}, - [0x4] = {DRM_FORMAT_AYUV, 32, - "YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"}, -}; - -/** - * intel_vgpu_decode_sprite_plane - Decode sprite plane - * @vgpu: input vgpu - * @plane: sprite plane to save decoded info - * This function is called for decoding plane - * - * Returns: - * 0 on success, non-zero if failed. - */ -int intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu, - struct intel_vgpu_sprite_plane_format *plane) -{ - u32 val, fmt; - u32 color_order, yuv_order; - int drm_format; - int pipe; - - pipe = get_active_pipe(vgpu); - if (pipe >= I915_MAX_PIPES) - return -ENODEV; - - val = vgpu_vreg_t(vgpu, SPRCTL(pipe)); - plane->enabled = !!(val & SPRITE_ENABLE); - if (!plane->enabled) - return -ENODEV; - - plane->tiled = !!(val & SPRITE_TILED); - color_order = !!(val & SPRITE_RGB_ORDER_RGBX); - yuv_order = (val & SPRITE_YUV_ORDER_MASK) >> - _SPRITE_YUV_ORDER_SHIFT; - - fmt = (val & SPRITE_FORMAT_MASK) >> _SPRITE_FMT_SHIFT; - if (!sprite_pixel_formats[fmt].bpp) { - gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt); - return -EINVAL; - } - plane->hw_format = fmt; - plane->bpp = sprite_pixel_formats[fmt].bpp; - drm_format = sprite_pixel_formats[fmt].drm_format; - - /* Order of RGB values in an RGBxxx buffer may be ordered RGB or - * BGR depending on the state of the color_order field - */ - if (!color_order) { - if (drm_format == DRM_FORMAT_XRGB2101010) - drm_format = DRM_FORMAT_XBGR2101010; - else if (drm_format == DRM_FORMAT_XRGB8888) - drm_format = DRM_FORMAT_XBGR8888; - } - - if (drm_format == DRM_FORMAT_YUV422) { - switch (yuv_order) { - case 0: - drm_format = DRM_FORMAT_YUYV; - break; - case 1: - drm_format = DRM_FORMAT_UYVY; - break; - case 2: - drm_format = DRM_FORMAT_YVYU; - break; - case 3: - drm_format = DRM_FORMAT_VYUY; - break; - default: - /* yuv_order has only 2 bits */ - break; - } - } - - plane->drm_format = drm_format; - - plane->base = vgpu_vreg_t(vgpu, SPRSURF(pipe)) & I915_GTT_PAGE_MASK; - if (!vgpu_gmadr_is_valid(vgpu, plane->base)) - return -EINVAL; - - plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); - if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { - gvt_vgpu_err("Translate sprite plane gma 0x%x to gpa fail\n", - plane->base); - return -EINVAL; - } - - plane->stride = vgpu_vreg_t(vgpu, SPRSTRIDE(pipe)) & - _SPRITE_STRIDE_MASK; - - val = vgpu_vreg_t(vgpu, SPRSIZE(pipe)); - plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >> - _SPRITE_SIZE_HEIGHT_SHIFT; - plane->width = (val & _SPRITE_SIZE_WIDTH_MASK) >> - _SPRITE_SIZE_WIDTH_SHIFT; - plane->height += 1; /* raw height is one minus the real value */ - plane->width += 1; /* raw width is one minus the real value */ - - val = vgpu_vreg_t(vgpu, SPRPOS(pipe)); - plane->x_pos = (val & _SPRITE_POS_X_MASK) >> _SPRITE_POS_X_SHIFT; - plane->y_pos = (val & _SPRITE_POS_Y_MASK) >> _SPRITE_POS_Y_SHIFT; - - val = vgpu_vreg_t(vgpu, SPROFFSET(pipe)); - plane->x_offset = (val & _SPRITE_OFFSET_START_X_MASK) >> - _SPRITE_OFFSET_START_X_SHIFT; - plane->y_offset = (val & _SPRITE_OFFSET_START_Y_MASK) >> - _SPRITE_OFFSET_START_Y_SHIFT; - - return 0; -} diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h index fa6503900c84..436d43c0087b 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.h +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h @@ -156,7 +156,5 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, struct intel_vgpu_primary_plane_format *plane); int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, struct intel_vgpu_cursor_plane_format *plane); -int intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu, - struct intel_vgpu_sprite_plane_format *plane); #endif -- cgit v1.2.3-59-g8ed1b From 4e19eabc7e5c03da09a53fc05caecab3aa18ee0d Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Sun, 22 Dec 2024 00:20:43 +0000 Subject: drm/i915/gvt: Remove unused intel_gvt_in_force_nonpriv_whitelist The last use of intel_gvt_in_force_nonpriv_whitelist() was removed in 2020 by commit 02dd2b12a685 ("drm/i915/gvt: unify lri cmd handler and mmio handlers") Remove it. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Zhenyu Wang Link: https://patchwork.freedesktop.org/patch/msgid/20241222002043.173080-4-linux@treblig.org Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/handlers.c | 17 ----------------- drivers/gpu/drm/i915/gvt/mmio.h | 3 --- 2 files changed, 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 241cff0fc683..ee473b45d1e4 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -3118,23 +3118,6 @@ int intel_vgpu_mask_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; } -/** - * intel_gvt_in_force_nonpriv_whitelist - if a mmio is in whitelist to be - * force-nopriv register - * - * @gvt: a GVT device - * @offset: register offset - * - * Returns: - * True if the register is in force-nonpriv whitelist; - * False if outside; - */ -bool intel_gvt_in_force_nonpriv_whitelist(struct intel_gvt *gvt, - unsigned int offset) -{ - return in_whitelist(offset); -} - /** * intel_vgpu_mmio_reg_rw - emulate tracked mmio registers * @vgpu: a vGPU diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index 32ebacb078e8..3dc912aba80b 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h @@ -96,9 +96,6 @@ int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes); -bool intel_gvt_in_force_nonpriv_whitelist(struct intel_gvt *gvt, - unsigned int offset); - int intel_vgpu_mmio_reg_rw(struct intel_vgpu *vgpu, unsigned int offset, void *pdata, unsigned int bytes, bool is_read); -- cgit v1.2.3-59-g8ed1b From 0ca6d6058852857c628b479f1e7aad3386036bdb Mon Sep 17 00:00:00 2001 From: Langyan Ye Date: Wed, 25 Dec 2024 10:01:09 +0800 Subject: drm/panel-edp: Add B140UAN04.4 and MNE007QS3-7 The raw edid for B140UAN04.4 panel is: 00 ff ff ff ff ff ff 00 06 af b3 a7 00 00 00 00 0c 22 01 04 a5 1e 13 78 03 cb 55 91 57 5a 91 29 1c 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 f4 3c 80 b8 70 b0 24 40 10 10 3e 00 2d bc 10 00 00 18 00 00 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 fe 00 41 55 4f 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe 00 42 31 34 30 55 41 4e 30 34 2e 34 20 0a 01 46 70 20 79 02 00 22 00 14 87 61 02 85 7f 07 b7 00 0f 80 0f 00 af 04 23 00 02 00 0d 00 25 01 09 87 61 02 87 61 02 28 3c 80 81 00 15 74 1a 00 00 03 01 28 3c 00 00 53 50 53 50 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 90 The raw edid for MNE007QS3-7 panel is: 00 ff ff ff ff ff ff 00 0e 77 48 14 00 00 00 00 34 20 01 04 a5 1e 13 78 03 2c c5 94 5c 59 95 29 1e 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ea 3d 80 c8 70 b0 2e 40 30 20 36 00 2e bd 10 00 00 1a 00 00 00 fd 00 28 3c 4b 4b 10 01 0a 20 20 20 20 20 20 00 00 00 fe 00 43 53 4f 54 20 54 39 0a 20 20 20 20 20 00 00 00 fe 00 4d 4e 45 30 30 37 51 53 33 2d 37 0a 20 00 df Signed-off-by: Langyan Ye [dianders: adjusted sort ordering] Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20241225020109.1051449-1-yelangyan@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-edp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index f8511fe5fb0d..2080f400bb65 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1862,6 +1862,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('A', 'U', 'O', 0x73aa, &delay_200_500_e50, "B116XTN02.3"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xa199, &delay_200_500_e50, "B116XAN06.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0xa7b3, &delay_200_500_e50, "B140UAN04.4"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xc4b4, &delay_200_500_e50, "B116XAT04.1"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xd497, &delay_200_500_e50, "B120XAN01.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0xf390, &delay_200_500_e50, "B140XTN07.7"), @@ -1954,6 +1955,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'S', 'W', 0x1100, &delay_200_500_e80_d50, "MNB601LS1-1"), EDP_PANEL_ENTRY('C', 'S', 'W', 0x1104, &delay_200_500_e50, "MNB601LS1-4"), + EDP_PANEL_ENTRY('C', 'S', 'W', 0x1448, &delay_200_500_e50, "MNE007QS3-7"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d51, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5b, &delay_200_500_e200, "MB116AN01"), -- cgit v1.2.3-59-g8ed1b From 29e93d0a04b6c546a2557486029219e5f6146e65 Mon Sep 17 00:00:00 2001 From: Langyan Ye Date: Fri, 27 Dec 2024 18:19:13 +0800 Subject: drm/panel-edp: Add CSW MNB601LS1-3 Add support for the CSW MNB601LS1-3, pleace the EDID here for subsequent reference. 00 ff ff ff ff ff ff 00 0e 77 03 11 00 00 00 00 00 22 01 04 95 1a 0e 78 03 a1 35 9b 5e 58 91 25 1c 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 09 1e 56 dc 50 00 28 30 30 20 36 00 00 90 10 00 00 1a 00 00 00 fd 00 28 3c 30 30 08 01 0a 20 20 20 20 20 20 00 00 00 fe 00 43 53 4f 54 20 54 39 0a 20 20 20 20 20 00 00 00 fe 00 4d 4e 42 36 30 31 4c 53 31 2d 33 0a 20 00 32 Signed-off-by: Langyan Ye Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20241227101913.1711071-1-yelangyan@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 2080f400bb65..2e1081caff93 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1954,6 +1954,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'S', 'O', 0x1200, &delay_200_500_e50_p2e200, "MNC207QS1-1"), EDP_PANEL_ENTRY('C', 'S', 'W', 0x1100, &delay_200_500_e80_d50, "MNB601LS1-1"), + EDP_PANEL_ENTRY('C', 'S', 'W', 0x1103, &delay_200_500_e80_d50, "MNB601LS1-3"), EDP_PANEL_ENTRY('C', 'S', 'W', 0x1104, &delay_200_500_e50, "MNB601LS1-4"), EDP_PANEL_ENTRY('C', 'S', 'W', 0x1448, &delay_200_500_e50, "MNE007QS3-7"), -- cgit v1.2.3-59-g8ed1b From 749b5b279e5636cdcef51e15d67b77162cca6caa Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 9 Jan 2025 14:28:53 -0800 Subject: drm/panel-edp: Add Starry 116KHD024006 We have a few reports of sc7180-trogdor-pompom devices that have a panel in them that IDs as STA 0x0004 and has the following raw EDID: 00 ff ff ff ff ff ff 00 4e 81 04 00 00 00 00 00 10 20 01 04 a5 1a 0e 78 0a dc dd 96 5b 5b 91 28 1f 52 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 8e 1c 56 a0 50 00 1e 30 28 20 55 00 00 90 10 00 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe 00 31 31 36 4b 48 44 30 32 34 30 30 36 0a 00 e6 We've been unable to locate a datasheet for this panel and our partner has not been responsive, but all Starry eDP datasheets that we can find agree on the same timing (delay_100_500_e200) so it should be safe to use that here instead of the super conservative timings. We'll still go a little extra conservative and allow `hpd_absent` of 200 instead of 100 because that won't add any real-world delay in most cases. We'll associate the string from the EDID ("116KHD024006") with this panel. Given that the ID is the suspicious value of 0x0004 it seems likely that Starry doesn't always update their IDs but the string will still work to differentiate if we ever need to in the future. Reviewed-by: Neil Armstrong Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250109142853.1.Ibcc3009933fd19507cc9c713ad0c99c7a9e4fe17@changeid --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 2e1081caff93..319ebc184c16 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1996,6 +1996,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"), EDP_PANEL_ENTRY('S', 'H', 'P', 0x1593, &delay_200_500_p2e100, "LQ134N1"), + EDP_PANEL_ENTRY('S', 'T', 'A', 0x0004, &delay_200_500_e200, "116KHD024006"), EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"), { /* sentinal */ } -- cgit v1.2.3-59-g8ed1b From 4f7fad42aa1aefc2baca7ef91d955fbe6f133e28 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 10 Jan 2025 09:46:39 -0500 Subject: drm/i915/guc/slpc: Allow GuC SLPC default strategies on MTL+ The Balancer and DCC strategies were left off on a fear that these strategies would conflict with the i915's waitboost. However, on MTL and Beyond these strategies are only active in certain conditions where the system is TDP limited. So, they don't conflict, but help the waitboost by guaranteeing a bit more of GT frequency. Without these strategies we were likely leaving some performance behind on some scenarios. With this change in place, the enabling/disabling of DCC and Balancer will now be chosen by GuC, on a platform/GT basis. v2: - Fix typos and be clear on GuC decision on platform basis (Vinay) - Limit change to MTL and beyond, where GuC started to take TDP limit into consideration. v3: Fix compilation. Actually amend the changes... Reviewed-by: Vinay Belgaumkar Link: https://patchwork.freedesktop.org/patch/msgid/20250110144640.1032250-1-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 706fffca698b..1f8e6f7c2c67 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -357,21 +357,29 @@ static u32 slpc_decode_max_freq(struct intel_guc_slpc *slpc) GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); } -static void slpc_shared_data_reset(struct slpc_shared_data *data) +static void slpc_shared_data_reset(struct intel_guc_slpc *slpc) { - memset(data, 0, sizeof(struct slpc_shared_data)); + struct drm_i915_private *i915 = slpc_to_i915(slpc); + struct slpc_shared_data *data = slpc->vaddr; + memset(data, 0, sizeof(struct slpc_shared_data)); data->header.size = sizeof(struct slpc_shared_data); /* Enable only GTPERF task, disable others */ slpc_mem_set_enabled(data, SLPC_PARAM_TASK_ENABLE_GTPERF, SLPC_PARAM_TASK_DISABLE_GTPERF); - slpc_mem_set_disabled(data, SLPC_PARAM_TASK_ENABLE_BALANCER, - SLPC_PARAM_TASK_DISABLE_BALANCER); + /* + * Don't allow balancer related algorithms on platforms before + * Xe_LPG, where GuC started to restrict it to TDP limited scenarios. + */ + if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 70)) { + slpc_mem_set_disabled(data, SLPC_PARAM_TASK_ENABLE_BALANCER, + SLPC_PARAM_TASK_DISABLE_BALANCER); - slpc_mem_set_disabled(data, SLPC_PARAM_TASK_ENABLE_DCC, - SLPC_PARAM_TASK_DISABLE_DCC); + slpc_mem_set_disabled(data, SLPC_PARAM_TASK_ENABLE_DCC, + SLPC_PARAM_TASK_DISABLE_DCC); + } } /** @@ -686,7 +694,7 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) GEM_BUG_ON(!slpc->vma); - slpc_shared_data_reset(slpc->vaddr); + slpc_shared_data_reset(slpc); ret = slpc_reset(slpc); if (unlikely(ret < 0)) { -- cgit v1.2.3-59-g8ed1b From e0b0c6d2076d2b94122218259202030faaaac61d Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 10 Jan 2025 09:46:40 -0500 Subject: drm/i915/guc/slpc: Print more SLPC debug status information Let's peek on the Balancer and DCC status, now that we are using the default strategies. v2: fix identation v3: fix typo (Vinay) Reviewed-by: Vinay Belgaumkar Link: https://patchwork.freedesktop.org/patch/msgid/20250110144640.1032250-2-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 1f8e6f7c2c67..1a0e1a412fdb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -799,6 +799,23 @@ int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p drm_printf(p, "\tSLPC state: %s\n", slpc_get_state_string(slpc)); drm_printf(p, "\tGTPERF task active: %s\n", str_yes_no(slpc_tasks->status & SLPC_GTPERF_TASK_ENABLED)); + drm_printf(p, "\tDCC enabled: %s\n", + str_yes_no(slpc_tasks->status & + SLPC_DCC_TASK_ENABLED)); + drm_printf(p, "\tDCC in: %s\n", + str_yes_no(slpc_tasks->status & SLPC_IN_DCC)); + drm_printf(p, "\tBalancer enabled: %s\n", + str_yes_no(slpc_tasks->status & + SLPC_BALANCER_ENABLED)); + drm_printf(p, "\tIBC enabled: %s\n", + str_yes_no(slpc_tasks->status & + SLPC_IBC_TASK_ENABLED)); + drm_printf(p, "\tBalancer IA LMT enabled: %s\n", + str_yes_no(slpc_tasks->status & + SLPC_BALANCER_IA_LMT_ENABLED)); + drm_printf(p, "\tBalancer IA LMT active: %s\n", + str_yes_no(slpc_tasks->status & + SLPC_BALANCER_IA_LMT_ACTIVE)); drm_printf(p, "\tMax freq: %u MHz\n", slpc_decode_max_freq(slpc)); drm_printf(p, "\tMin freq: %u MHz\n", -- cgit v1.2.3-59-g8ed1b From ed3a892e5e3d6b3f6eeb76db7c92a968aeb52f3d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2024 08:50:11 +0200 Subject: drm/i915/fb: Relax clear color alignment to 64 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mesa changed its clear color alignment from 4k to 64 bytes without informing the kernel side about the change. This is now likely to cause framebuffer creation to fail. The only thing we do with the clear color buffer in i915 is: 1. map a single page 2. read out bytes 16-23 from said page 3. unmap the page So the only requirement we really have is that those 8 bytes are all contained within one page. Thus we can deal with the Mesa regression by reducing the alignment requiment from 4k to the same 64 bytes in the kernel. We could even go as low as 32 bytes, but IIRC 64 bytes is the hardware requirement on the 3D engine side so matching that seems sensible. Note that the Mesa alignment chages were partially undone so the regression itself was already fixed on userspace side. Cc: stable@vger.kernel.org Cc: Sagar Ghuge Cc: Nanley Chery Reported-by: Xi Ruoyao Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13057 Closes: https://lore.kernel.org/all/45a5bba8de009347262d86a4acb27169d9ae0d9f.camel@xry111.site/ Link: https://gitlab.freedesktop.org/mesa/mesa/-/commit/17f97a69c13832a6c1b0b3aad45b06f07d4b852f Link: https://gitlab.freedesktop.org/mesa/mesa/-/commit/888f63cf1baf34bc95e847a30a041dc7798edddb Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241129065014.8363-2-ville.syrjala@linux.intel.com Tested-by: Xi Ruoyao Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 6a7060889f40..223c4218c019 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1694,7 +1694,7 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * * arithmetic related to alignment and offset calculation. */ if (is_gen12_ccs_cc_plane(&fb->base, i)) { - if (IS_ALIGNED(fb->base.offsets[i], PAGE_SIZE)) + if (IS_ALIGNED(fb->base.offsets[i], 64)) continue; else return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 0bd39e303ee705c4b0549e2826c42c1d7b849898 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2024 08:50:12 +0200 Subject: drm/i915/fb: Add debug spew for misaligned CC plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're currently failing to provide any debug output when the user passes in a misaligned offset for the clear color plane. Add some debugs prints to make debugging actually possible. Cc: Sagar Ghuge Cc: Nanley Chery Cc: Xi Ruoyao Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241129065014.8363-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_fb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 223c4218c019..e478d412785e 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1694,10 +1694,14 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * * arithmetic related to alignment and offset calculation. */ if (is_gen12_ccs_cc_plane(&fb->base, i)) { - if (IS_ALIGNED(fb->base.offsets[i], 64)) - continue; - else + if (!IS_ALIGNED(fb->base.offsets[i], 64)) { + drm_dbg_kms(&i915->drm, + "fb misaligned clear color plane %d offset (0x%x)\n", + i, fb->base.offsets[i]); return -EINVAL; + } + + continue; } intel_fb_plane_dims(fb, i, &width, &height); -- cgit v1.2.3-59-g8ed1b From b9ec6793355647bcbcecb21ef6cd179469d3f191 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2024 08:50:13 +0200 Subject: drm/i915/fb: Check that the clear color fits within the BO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure the user supplied offset[] for the clear color plane fits within the actual BO. Note that we use tile units to track the size here. All the other color/aux planes are already being checked correctly. Cc: Sagar Ghuge Cc: Nanley Chery Cc: Xi Ruoyao Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241129065014.8363-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_fb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index e478d412785e..9f7f1b9f3275 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1694,6 +1694,8 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * * arithmetic related to alignment and offset calculation. */ if (is_gen12_ccs_cc_plane(&fb->base, i)) { + unsigned int end; + if (!IS_ALIGNED(fb->base.offsets[i], 64)) { drm_dbg_kms(&i915->drm, "fb misaligned clear color plane %d offset (0x%x)\n", @@ -1701,6 +1703,14 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * return -EINVAL; } + if (check_add_overflow(fb->base.offsets[i], 64, &end)) { + drm_dbg_kms(&i915->drm, + "fb bad clear color plane %d offset (0x%x)\n", + i, fb->base.offsets[i]); + return -EINVAL; + } + + max_size = max(max_size, DIV_ROUND_UP(end, tile_size)); continue; } -- cgit v1.2.3-59-g8ed1b From 412576293cca1ec2e9c1532acb7a66e811dd8ceb Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Mon, 13 Jan 2025 10:26:16 -0800 Subject: accel/amdxdna: Remove casting mailbox payload pointer The mailbox payload pointer is void __iomem *. Casting it to u32 * is incorrect and causes sparse warning. cast removes address space '__iomem' of expression Fixes: b87f920b9344 ("accel/amdxdna: Support hardware mailbox") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501130921.ktqwsMLH-lkp@intel.com/ Signed-off-by: Lizhi Hou Reviewed-by: Mario Limonciello Signed-off-by: Mario Limonciello Link: https://patchwork.freedesktop.org/patch/msgid/20250113182617.1256094-1-lizhi.hou@amd.com --- drivers/accel/amdxdna/aie2_ctx.c | 22 +++++++++++----------- drivers/accel/amdxdna/aie2_error.c | 8 +++----- drivers/accel/amdxdna/aie2_message.c | 10 +++++----- drivers/accel/amdxdna/aie2_pci.h | 10 +++++----- drivers/accel/amdxdna/amdxdna_mailbox.c | 6 +++--- drivers/accel/amdxdna/amdxdna_mailbox.h | 2 +- drivers/accel/amdxdna/amdxdna_mailbox_helper.c | 6 +++--- drivers/accel/amdxdna/amdxdna_mailbox_helper.h | 2 +- 8 files changed, 32 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 5f43db02b240..5c69ae3c40f8 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -185,7 +185,7 @@ aie2_sched_notify(struct amdxdna_sched_job *job) } static int -aie2_sched_resp_handler(void *handle, const u32 *data, size_t size) +aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size) { struct amdxdna_sched_job *job = handle; struct amdxdna_gem_obj *cmd_abo; @@ -203,7 +203,7 @@ aie2_sched_resp_handler(void *handle, const u32 *data, size_t size) goto out; } - status = *data; + status = readl(data); XDNA_DBG(job->hwctx->client->xdna, "Resp status 0x%x", status); if (status == AIE2_STATUS_SUCCESS) amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_COMPLETED); @@ -216,7 +216,7 @@ out: } static int -aie2_sched_nocmd_resp_handler(void *handle, const u32 *data, size_t size) +aie2_sched_nocmd_resp_handler(void *handle, void __iomem *data, size_t size) { struct amdxdna_sched_job *job = handle; u32 ret = 0; @@ -230,7 +230,7 @@ aie2_sched_nocmd_resp_handler(void *handle, const u32 *data, size_t size) goto out; } - status = *data; + status = readl(data); XDNA_DBG(job->hwctx->client->xdna, "Resp status 0x%x", status); out: @@ -239,14 +239,14 @@ out: } static int -aie2_sched_cmdlist_resp_handler(void *handle, const u32 *data, size_t size) +aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size) { struct amdxdna_sched_job *job = handle; struct amdxdna_gem_obj *cmd_abo; - struct cmd_chain_resp *resp; struct amdxdna_dev *xdna; u32 fail_cmd_status; u32 fail_cmd_idx; + u32 cmd_status; u32 ret = 0; cmd_abo = job->cmd_bo; @@ -256,17 +256,17 @@ aie2_sched_cmdlist_resp_handler(void *handle, const u32 *data, size_t size) goto out; } - resp = (struct cmd_chain_resp *)data; + cmd_status = readl(data + offsetof(struct cmd_chain_resp, status)); xdna = job->hwctx->client->xdna; - XDNA_DBG(xdna, "Status 0x%x", resp->status); - if (resp->status == AIE2_STATUS_SUCCESS) { + XDNA_DBG(xdna, "Status 0x%x", cmd_status); + if (cmd_status == AIE2_STATUS_SUCCESS) { amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_COMPLETED); goto out; } /* Slow path to handle error, read from ringbuf on BAR */ - fail_cmd_idx = resp->fail_cmd_idx; - fail_cmd_status = resp->fail_cmd_status; + fail_cmd_idx = readl(data + offsetof(struct cmd_chain_resp, fail_cmd_idx)); + fail_cmd_status = readl(data + offsetof(struct cmd_chain_resp, fail_cmd_status)); XDNA_DBG(xdna, "Failed cmd idx %d, status 0x%x", fail_cmd_idx, fail_cmd_status); diff --git a/drivers/accel/amdxdna/aie2_error.c b/drivers/accel/amdxdna/aie2_error.c index b1defaa8513b..5ee905632a39 100644 --- a/drivers/accel/amdxdna/aie2_error.c +++ b/drivers/accel/amdxdna/aie2_error.c @@ -209,16 +209,14 @@ static u32 aie2_error_backtrack(struct amdxdna_dev_hdl *ndev, void *err_info, u3 return err_col; } -static int aie2_error_async_cb(void *handle, const u32 *data, size_t size) +static int aie2_error_async_cb(void *handle, void __iomem *data, size_t size) { - struct async_event_msg_resp *resp; struct async_event *e = handle; if (data) { - resp = (struct async_event_msg_resp *)data; - e->resp.type = resp->type; + e->resp.type = readl(data + offsetof(struct async_event_msg_resp, type)); wmb(); /* Update status in the end, so that no lock for here */ - e->resp.status = resp->status; + e->resp.status = readl(data + offsetof(struct async_event_msg_resp, status)); } queue_work(e->wq, &e->work); return 0; diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c index 9e2c9a44f76a..bf4219e32cc1 100644 --- a/drivers/accel/amdxdna/aie2_message.c +++ b/drivers/accel/amdxdna/aie2_message.c @@ -356,7 +356,7 @@ fail: } int aie2_register_asyn_event_msg(struct amdxdna_dev_hdl *ndev, dma_addr_t addr, u32 size, - void *handle, int (*cb)(void*, const u32 *, size_t)) + void *handle, int (*cb)(void*, void __iomem *, size_t)) { struct async_event_msg_req req = { 0 }; struct xdna_mailbox_msg msg = { @@ -435,7 +435,7 @@ int aie2_config_cu(struct amdxdna_hwctx *hwctx) } int aie2_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)) + int (*notify_cb)(void *, void __iomem *, size_t)) { struct mailbox_channel *chann = hwctx->priv->mbox_chann; struct amdxdna_dev *xdna = hwctx->client->xdna; @@ -640,7 +640,7 @@ aie2_cmd_op_to_msg_op(u32 op) int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)) + int (*notify_cb)(void *, void __iomem *, size_t)) { struct amdxdna_gem_obj *cmdbuf_abo = aie2_cmdlist_get_cmd_buf(job); struct mailbox_channel *chann = hwctx->priv->mbox_chann; @@ -705,7 +705,7 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx, int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)) + int (*notify_cb)(void *, void __iomem *, size_t)) { struct amdxdna_gem_obj *cmdbuf_abo = aie2_cmdlist_get_cmd_buf(job); struct mailbox_channel *chann = hwctx->priv->mbox_chann; @@ -740,7 +740,7 @@ int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx, } int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)) + int (*notify_cb)(void *, void __iomem *, size_t)) { struct mailbox_channel *chann = hwctx->priv->mbox_chann; struct amdxdna_gem_obj *abo = to_xdna_obj(job->bos[0]); diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h index f2d95531ddc2..385914840eaa 100644 --- a/drivers/accel/amdxdna/aie2_pci.h +++ b/drivers/accel/amdxdna/aie2_pci.h @@ -271,18 +271,18 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc int aie2_map_host_buf(struct amdxdna_dev_hdl *ndev, u32 context_id, u64 addr, u64 size); int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf, u32 size, u32 *cols_filled); int aie2_register_asyn_event_msg(struct amdxdna_dev_hdl *ndev, dma_addr_t addr, u32 size, - void *handle, int (*cb)(void*, const u32 *, size_t)); + void *handle, int (*cb)(void*, void __iomem *, size_t)); int aie2_config_cu(struct amdxdna_hwctx *hwctx); int aie2_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)); + int (*notify_cb)(void *, void __iomem *, size_t)); int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)); + int (*notify_cb)(void *, void __iomem *, size_t)); int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)); + int (*notify_cb)(void *, void __iomem *, size_t)); int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, - int (*notify_cb)(void *, const u32 *, size_t)); + int (*notify_cb)(void *, void __iomem *, size_t)); /* aie2_hwctx.c */ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx); diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.c b/drivers/accel/amdxdna/amdxdna_mailbox.c index 814b16bb1953..de7bf0fb4594 100644 --- a/drivers/accel/amdxdna/amdxdna_mailbox.c +++ b/drivers/accel/amdxdna/amdxdna_mailbox.c @@ -90,7 +90,7 @@ struct mailbox_pkg { struct mailbox_msg { void *handle; - int (*notify_cb)(void *handle, const u32 *data, size_t size); + int (*notify_cb)(void *handle, void __iomem *data, size_t size); size_t pkg_size; /* package size in bytes */ struct mailbox_pkg pkg; }; @@ -243,7 +243,7 @@ no_space: static int mailbox_get_resp(struct mailbox_channel *mb_chann, struct xdna_msg_header *header, - void *data) + void __iomem *data) { struct mailbox_msg *mb_msg; int msg_id; @@ -331,7 +331,7 @@ static int mailbox_get_msg(struct mailbox_channel *mb_chann) memcpy_fromio((u32 *)&header + 1, read_addr, rest); read_addr += rest; - ret = mailbox_get_resp(mb_chann, &header, (u32 *)read_addr); + ret = mailbox_get_resp(mb_chann, &header, read_addr); mailbox_set_headptr(mb_chann, head + msg_size); /* After update head, it can equal to ringbuf_size. This is expected. */ diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.h b/drivers/accel/amdxdna/amdxdna_mailbox.h index 57954c303bdd..ea367f2fb738 100644 --- a/drivers/accel/amdxdna/amdxdna_mailbox.h +++ b/drivers/accel/amdxdna/amdxdna_mailbox.h @@ -25,7 +25,7 @@ struct mailbox_channel; struct xdna_mailbox_msg { u32 opcode; void *handle; - int (*notify_cb)(void *handle, const u32 *data, size_t size); + int (*notify_cb)(void *handle, void __iomem *data, size_t size); u8 *send_data; size_t send_size; }; diff --git a/drivers/accel/amdxdna/amdxdna_mailbox_helper.c b/drivers/accel/amdxdna/amdxdna_mailbox_helper.c index 5139a9c96a91..6d0c24513476 100644 --- a/drivers/accel/amdxdna/amdxdna_mailbox_helper.c +++ b/drivers/accel/amdxdna/amdxdna_mailbox_helper.c @@ -16,7 +16,7 @@ #include "amdxdna_mailbox_helper.h" #include "amdxdna_pci_drv.h" -int xdna_msg_cb(void *handle, const u32 *data, size_t size) +int xdna_msg_cb(void *handle, void __iomem *data, size_t size) { struct xdna_notify *cb_arg = handle; int ret; @@ -29,9 +29,9 @@ int xdna_msg_cb(void *handle, const u32 *data, size_t size) goto out; } + memcpy_fromio(cb_arg->data, data, cb_arg->size); print_hex_dump_debug("resp data: ", DUMP_PREFIX_OFFSET, - 16, 4, data, cb_arg->size, true); - memcpy(cb_arg->data, data, cb_arg->size); + 16, 4, cb_arg->data, cb_arg->size, true); out: ret = cb_arg->error; complete(&cb_arg->comp); diff --git a/drivers/accel/amdxdna/amdxdna_mailbox_helper.h b/drivers/accel/amdxdna/amdxdna_mailbox_helper.h index 23e1317b79fe..710ff8873d61 100644 --- a/drivers/accel/amdxdna/amdxdna_mailbox_helper.h +++ b/drivers/accel/amdxdna/amdxdna_mailbox_helper.h @@ -35,7 +35,7 @@ struct xdna_notify { .notify_cb = xdna_msg_cb, \ } -int xdna_msg_cb(void *handle, const u32 *data, size_t size); +int xdna_msg_cb(void *handle, void __iomem *data, size_t size); int xdna_send_msg_wait(struct amdxdna_dev *xdna, struct mailbox_channel *chann, struct xdna_mailbox_msg *msg); -- cgit v1.2.3-59-g8ed1b From b3dff598e72f58888f39588d621913eddb9f9313 Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Mon, 13 Jan 2025 10:26:17 -0800 Subject: accel/amdxdna: Declare sched_ops as static Fix sparse warning: symbol 'sched_ops' was not declared. Should it be static? Fixes: aac243092b70 ("accel/amdxdna: Add command execution") Signed-off-by: Lizhi Hou Reviewed-by: Mario Limonciello Signed-off-by: Mario Limonciello Link: https://patchwork.freedesktop.org/patch/msgid/20250113182617.1256094-2-lizhi.hou@amd.com --- drivers/accel/amdxdna/aie2_ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 5c69ae3c40f8..2799729801f6 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -361,7 +361,7 @@ aie2_sched_job_timedout(struct drm_sched_job *sched_job) return DRM_GPU_SCHED_STAT_NOMINAL; } -const struct drm_sched_backend_ops sched_ops = { +static const struct drm_sched_backend_ops sched_ops = { .run_job = aie2_sched_job_run, .free_job = aie2_sched_job_free, .timedout_job = aie2_sched_job_timedout, -- cgit v1.2.3-59-g8ed1b From c26f22dac3449d8a687237cdfc59a6445eb8f75a Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Fri, 10 Jan 2025 18:15:39 -0800 Subject: drm/xe/oa: Add missing VISACTL mux registers Add missing VISACTL mux registers required for some OA config's (e.g. RenderPipeCtrl). Fixes: cdf02fe1a94a ("drm/xe/oa/uapi: Add/remove OA config perf ops") Cc: stable@vger.kernel.org Signed-off-by: Ashutosh Dixit Reviewed-by: Umesh Nerlige Ramappa Link: https://patchwork.freedesktop.org/patch/msgid/20250111021539.2920346-1-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/xe_oa.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 4e00a77289c5..eeb96b5f49e2 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -2163,6 +2163,7 @@ static const struct xe_mmio_range xe2_oa_mux_regs[] = { { .start = 0x5194, .end = 0x5194 }, /* SYS_MEM_LAT_MEASURE_MERTF_GRP_3D */ { .start = 0x8704, .end = 0x8704 }, /* LMEM_LAT_MEASURE_MCFG_GRP */ { .start = 0xB1BC, .end = 0xB1BC }, /* L3_BANK_LAT_MEASURE_LBCF_GFX */ + { .start = 0xD0E0, .end = 0xD0F4 }, /* VISACTL */ { .start = 0xE18C, .end = 0xE18C }, /* SAMPLER_MODE */ { .start = 0xE590, .end = 0xE590 }, /* TDL_LSC_LAT_MEASURE_TDL_GFX */ { .start = 0x13000, .end = 0x137FC }, /* PES_0_PESL0 - PES_63_UPPER_PESL3 */ -- cgit v1.2.3-59-g8ed1b From 6e11ce84c514f3ad8c8c766e1328bf49d80a0325 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 15 Jul 2024 11:38:57 +0200 Subject: drm/probe-helper: Call connector detect functions in single helper Move the logic to call the connector's detect helper into a single internal function. Reduces code dupliction. Signed-off-by: Thomas Zimmermann Acked-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240715093936.793552-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_probe_helper.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 080b55200614..7ba16323e7c2 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -338,10 +338,23 @@ void drm_kms_helper_poll_reschedule(struct drm_device *dev) } EXPORT_SYMBOL(drm_kms_helper_poll_reschedule); +static int detect_connector_status(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + const struct drm_connector_helper_funcs *funcs = connector->helper_private; + + if (funcs->detect_ctx) + return funcs->detect_ctx(connector, ctx, force); + else if (connector->funcs->detect) + return connector->funcs->detect(connector, force); + + return connector_status_connected; +} + static enum drm_connector_status drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force) { - const struct drm_connector_helper_funcs *funcs = connector->helper_private; struct drm_modeset_acquire_ctx ctx; int ret; @@ -349,14 +362,8 @@ drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force) retry: ret = drm_modeset_lock(&connector->dev->mode_config.connection_mutex, &ctx); - if (!ret) { - if (funcs->detect_ctx) - ret = funcs->detect_ctx(connector, &ctx, force); - else if (connector->funcs->detect) - ret = connector->funcs->detect(connector, force); - else - ret = connector_status_connected; - } + if (!ret) + ret = detect_connector_status(connector, &ctx, force); if (ret == -EDEADLK) { drm_modeset_backoff(&ctx); @@ -390,7 +397,6 @@ drm_helper_probe_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force) { - const struct drm_connector_helper_funcs *funcs = connector->helper_private; struct drm_device *dev = connector->dev; int ret; @@ -401,12 +407,7 @@ drm_helper_probe_detect(struct drm_connector *connector, if (ret) return ret; - if (funcs->detect_ctx) - ret = funcs->detect_ctx(connector, ctx, force); - else if (connector->funcs->detect) - ret = connector->funcs->detect(connector, force); - else - ret = connector_status_connected; + ret = detect_connector_status(connector, ctx, force); if (ret != connector->status) connector->epoch_counter += 1; -- cgit v1.2.3-59-g8ed1b From d160dc6f53914d729be7fcb7afbd0e9e6a3725b2 Mon Sep 17 00:00:00 2001 From: Vinay Belgaumkar Date: Fri, 10 Jan 2025 09:33:09 -0800 Subject: drm/xe: Add locks in gtidle code The update of the residency values needs to be protected by a lock to avoid multiple entrypoints, for example when multiple userspace clients read the sysfs file. Other in-kernel clients are going to be added to sample these values, making the problem worse. Protect those updates with a raw_spinlock so it can be called by future integration with perf pmu. Suggested-by: Lucas De Marchi Cc: Rodrigo Vivi Cc: Lucas De Marchi Signed-off-by: Vinay Belgaumkar Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20250110173308.2412232-2-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_gt_idle.c | 23 ++++++++++++++++++++--- drivers/gpu/drm/xe/xe_gt_idle.h | 1 + drivers/gpu/drm/xe/xe_gt_idle_types.h | 3 +++ 3 files changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c index ffd3ba7f6656..fbbace7b0b12 100644 --- a/drivers/gpu/drm/xe/xe_gt_idle.c +++ b/drivers/gpu/drm/xe/xe_gt_idle.c @@ -69,6 +69,8 @@ static u64 get_residency_ms(struct xe_gt_idle *gtidle, u64 cur_residency) { u64 delta, overflow_residency, prev_residency; + lockdep_assert_held(>idle->lock); + overflow_residency = BIT_ULL(32); /* @@ -275,8 +277,21 @@ static ssize_t idle_status_show(struct device *dev, return sysfs_emit(buff, "%s\n", gt_idle_state_to_string(state)); } -static DEVICE_ATTR_RO(idle_status); +u64 xe_gt_idle_residency_msec(struct xe_gt_idle *gtidle) +{ + struct xe_guc_pc *pc = gtidle_to_pc(gtidle); + u64 residency; + unsigned long flags; + + raw_spin_lock_irqsave(>idle->lock, flags); + residency = get_residency_ms(gtidle, gtidle->idle_residency(pc)); + raw_spin_unlock_irqrestore(>idle->lock, flags); + + return residency; +} + +static DEVICE_ATTR_RO(idle_status); static ssize_t idle_residency_ms_show(struct device *dev, struct device_attribute *attr, char *buff) { @@ -285,10 +300,10 @@ static ssize_t idle_residency_ms_show(struct device *dev, u64 residency; xe_pm_runtime_get(pc_to_xe(pc)); - residency = gtidle->idle_residency(pc); + residency = xe_gt_idle_residency_msec(gtidle); xe_pm_runtime_put(pc_to_xe(pc)); - return sysfs_emit(buff, "%llu\n", get_residency_ms(gtidle, residency)); + return sysfs_emit(buff, "%llu\n", residency); } static DEVICE_ATTR_RO(idle_residency_ms); @@ -331,6 +346,8 @@ int xe_gt_idle_init(struct xe_gt_idle *gtidle) if (!kobj) return -ENOMEM; + raw_spin_lock_init(>idle->lock); + if (xe_gt_is_media_type(gt)) { snprintf(gtidle->name, sizeof(gtidle->name), "gt%d-mc", gt->info.id); gtidle->idle_residency = xe_guc_pc_mc6_residency; diff --git a/drivers/gpu/drm/xe/xe_gt_idle.h b/drivers/gpu/drm/xe/xe_gt_idle.h index 4455a6501cb0..591a01e181bc 100644 --- a/drivers/gpu/drm/xe/xe_gt_idle.h +++ b/drivers/gpu/drm/xe/xe_gt_idle.h @@ -17,5 +17,6 @@ void xe_gt_idle_disable_c6(struct xe_gt *gt); void xe_gt_idle_enable_pg(struct xe_gt *gt); void xe_gt_idle_disable_pg(struct xe_gt *gt); int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p); +u64 xe_gt_idle_residency_msec(struct xe_gt_idle *gtidle); #endif /* _XE_GT_IDLE_H_ */ diff --git a/drivers/gpu/drm/xe/xe_gt_idle_types.h b/drivers/gpu/drm/xe/xe_gt_idle_types.h index b8b297a3f884..a3667c567f8a 100644 --- a/drivers/gpu/drm/xe/xe_gt_idle_types.h +++ b/drivers/gpu/drm/xe/xe_gt_idle_types.h @@ -6,6 +6,7 @@ #ifndef _XE_GT_IDLE_SYSFS_TYPES_H_ #define _XE_GT_IDLE_SYSFS_TYPES_H_ +#include #include struct xe_guc_pc; @@ -31,6 +32,8 @@ struct xe_gt_idle { u64 cur_residency; /** @prev_residency: previous residency counter */ u64 prev_residency; + /** @lock: Lock protecting idle residency counters */ + raw_spinlock_t lock; /** @idle_status: get the current idle state */ enum xe_gt_idle_state (*idle_status)(struct xe_guc_pc *pc); /** @idle_residency: get idle residency counter */ -- cgit v1.2.3-59-g8ed1b From 467dce3817bd2b62ccd6fcfd7aae76f242ac907e Mon Sep 17 00:00:00 2001 From: "Lin.Cao" Date: Thu, 26 Dec 2024 12:31:15 +0530 Subject: drm/buddy: fix issue that force_merge cannot free all roots If buddy manager have more than one roots and each root have sub-block need to be free. When drm_buddy_fini called, the first loop of force_merge will merge and free all of the sub block of first root, which offset is 0x0 and size is biggest(more than have of the mm size). In subsequent force_merge rounds, if we use 0 as start and use remaining mm size as end, the block of other roots will be skipped in __force_merge function. It will cause the other roots can not be freed. Solution: use roots' offset as the start could fix this issue. Signed-off-by: Lin.Cao Signed-off-by: Arunpravin Paneer Selvam Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20241226070116.309290-1-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/drm_buddy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 103c185bb1c8..ca42e6081d27 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -324,7 +324,7 @@ EXPORT_SYMBOL(drm_buddy_init); */ void drm_buddy_fini(struct drm_buddy *mm) { - u64 root_size, size; + u64 root_size, size, start; unsigned int order; int i; @@ -332,7 +332,8 @@ void drm_buddy_fini(struct drm_buddy *mm) for (i = 0; i < mm->n_roots; ++i) { order = ilog2(size) - ilog2(mm->chunk_size); - __force_merge(mm, 0, size, order); + start = drm_buddy_block_offset(mm->roots[i]); + __force_merge(mm, start, start + size, order); WARN_ON(!drm_buddy_block_is_free(mm->roots[i])); drm_block_free(mm, mm->roots[i]); -- cgit v1.2.3-59-g8ed1b From 8cb3a1e2b3502341f7e5253842a74e511c13e5c9 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam Date: Thu, 26 Dec 2024 12:31:16 +0530 Subject: drm/buddy: Add a testcase to verify the multiroot fini - Added a testcase to verify the multiroot force merge fini. - Added a new field in_use to track the mm freed status. v2:(Matthew) - Add kunit_fail_current_test() when WARN_ON is true. Signed-off-by: Arunpravin Paneer Selvam Signed-off-by: Lin.Cao Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20241226070116.309290-2-Arunpravin.PaneerSelvam@amd.com --- drivers/gpu/drm/drm_buddy.c | 6 +++++- drivers/gpu/drm/tests/drm_buddy_test.c | 29 ++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index ca42e6081d27..241c855f891f 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -3,6 +3,8 @@ * Copyright © 2021 Intel Corporation */ +#include + #include #include #include @@ -335,7 +337,9 @@ void drm_buddy_fini(struct drm_buddy *mm) start = drm_buddy_block_offset(mm->roots[i]); __force_merge(mm, start, start + size, order); - WARN_ON(!drm_buddy_block_is_free(mm->roots[i])); + if (WARN_ON(!drm_buddy_block_is_free(mm->roots[i]))) + kunit_fail_current_test("buddy_fini() root"); + drm_block_free(mm, mm->roots[i]); root_size = mm->chunk_size << order; diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c index 9662c949d0e3..4b5818f9f2a9 100644 --- a/drivers/gpu/drm/tests/drm_buddy_test.c +++ b/drivers/gpu/drm/tests/drm_buddy_test.c @@ -385,17 +385,28 @@ static void drm_test_buddy_alloc_clear(struct kunit *test) drm_buddy_fini(&mm); /* - * Create a new mm with a non power-of-two size. Allocate a random size, free as - * cleared and then call fini. This will ensure the multi-root force merge during - * fini. + * Create a new mm with a non power-of-two size. Allocate a random size from each + * root, free as cleared and then call fini. This will ensure the multi-root + * force merge during fini. */ - mm_size = 12 * SZ_4K; - size = max(round_up(prandom_u32_state(&prng) % mm_size, ps), ps); + mm_size = (SZ_4K << max_order) + (SZ_4K << (max_order - 2)); + KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, - size, ps, &allocated, - DRM_BUDDY_TOPDOWN_ALLOCATION), - "buddy_alloc hit an error size=%u\n", size); + KUNIT_EXPECT_EQ(test, mm.max_order, max_order); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, SZ_4K << max_order, + 4 * ps, ps, &allocated, + DRM_BUDDY_RANGE_ALLOCATION), + "buddy_alloc hit an error size=%lu\n", 4 * ps); + drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, SZ_4K << max_order, + 2 * ps, ps, &allocated, + DRM_BUDDY_CLEAR_ALLOCATION), + "buddy_alloc hit an error size=%lu\n", 2 * ps); + drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); + KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, SZ_4K << max_order, mm_size, + ps, ps, &allocated, + DRM_BUDDY_RANGE_ALLOCATION), + "buddy_alloc hit an error size=%lu\n", ps); drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); drm_buddy_fini(&mm); } -- cgit v1.2.3-59-g8ed1b From 1b242ceec53627a93129ee076b94f8eb321e5a79 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 8 Jan 2025 16:04:13 +0200 Subject: drm/i915/audio: convert to struct intel_display Going forward, struct intel_display will be the main display device structure. Convert intel_audio.[ch] to it, as much as possible anyway. Do some minor checkpatch fixes while at it. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/4ddcc2e704fc6b1592a878c80e15fadd82c63550.1736345025.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_audio.c | 413 +++++++++++---------- drivers/gpu/drm/i915/display/intel_audio.h | 14 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 5 +- .../gpu/drm/i915/display/intel_display_driver.c | 10 +- drivers/gpu/drm/xe/display/xe_display.c | 2 +- 5 files changed, 226 insertions(+), 218 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index ce8a4319a63c..8c26e0e7c2cd 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -188,15 +188,15 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = { * WA_14020863754: Implement Audio Workaround * Corner case with Min Hblank Fix can cause audio hang */ -static bool needs_wa_14020863754(struct drm_i915_private *i915) +static bool needs_wa_14020863754(struct intel_display *display) { - return (DISPLAY_VER(i915) == 20 || IS_BATTLEMAGE(i915)); + return DISPLAY_VER(display) == 20 || display->platform.battlemage; } /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct intel_display *display = to_intel_display(crtc_state); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int i; @@ -206,17 +206,17 @@ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_sta break; } - if (DISPLAY_VER(i915) < 12 && adjusted_mode->crtc_clock > 148500) + if (DISPLAY_VER(display) < 12 && adjusted_mode->crtc_clock > 148500) i = ARRAY_SIZE(hdmi_audio_clock); if (i == ARRAY_SIZE(hdmi_audio_clock)) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "HDMI audio pixel clock setting for %d not found, falling back to defaults\n", adjusted_mode->crtc_clock); i = 1; } - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "Configuring HDMI audio for pixel clock %d (0x%08x)\n", hdmi_audio_clock[i].clock, hdmi_audio_clock[i].config); @@ -251,11 +251,11 @@ static int audio_config_hdmi_get_n(const struct intel_crtc_state *crtc_state, } /* ELD buffer size in dwords */ -static int g4x_eld_buffer_size(struct drm_i915_private *i915) +static int g4x_eld_buffer_size(struct intel_display *display) { u32 tmp; - tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); + tmp = intel_de_read(display, G4X_AUD_CNTL_ST); return REG_FIELD_GET(G4X_ELD_BUFFER_SIZE_MASK, tmp); } @@ -263,33 +263,33 @@ static int g4x_eld_buffer_size(struct drm_i915_private *i915) static void g4x_audio_codec_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); u32 *eld = (u32 *)crtc_state->eld; int eld_buffer_size, len, i; u32 tmp; - tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); + tmp = intel_de_read(display, G4X_AUD_CNTL_ST); if ((tmp & G4X_ELD_VALID) == 0) return; - intel_de_rmw(i915, G4X_AUD_CNTL_ST, G4X_ELD_ADDRESS_MASK, 0); + intel_de_rmw(display, G4X_AUD_CNTL_ST, G4X_ELD_ADDRESS_MASK, 0); - eld_buffer_size = g4x_eld_buffer_size(i915); + eld_buffer_size = g4x_eld_buffer_size(display); len = min_t(int, sizeof(crtc_state->eld) / 4, eld_buffer_size); for (i = 0; i < len; i++) - eld[i] = intel_de_read(i915, G4X_HDMIW_HDMIEDID); + eld[i] = intel_de_read(display, G4X_HDMIW_HDMIEDID); } static void g4x_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); /* Invalidate ELD */ - intel_de_rmw(i915, G4X_AUD_CNTL_ST, + intel_de_rmw(display, G4X_AUD_CNTL_ST, G4X_ELD_VALID, 0); intel_crtc_wait_for_next_vblank(crtc); @@ -300,28 +300,28 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const u32 *eld = (const u32 *)crtc_state->eld; int eld_buffer_size, len, i; intel_crtc_wait_for_next_vblank(crtc); - intel_de_rmw(i915, G4X_AUD_CNTL_ST, + intel_de_rmw(display, G4X_AUD_CNTL_ST, G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0); - eld_buffer_size = g4x_eld_buffer_size(i915); + eld_buffer_size = g4x_eld_buffer_size(display); len = min(drm_eld_size(crtc_state->eld) / 4, eld_buffer_size); for (i = 0; i < len; i++) - intel_de_write(i915, G4X_HDMIW_HDMIEDID, eld[i]); + intel_de_write(display, G4X_HDMIW_HDMIEDID, eld[i]); for (; i < eld_buffer_size; i++) - intel_de_write(i915, G4X_HDMIW_HDMIEDID, 0); + intel_de_write(display, G4X_HDMIW_HDMIEDID, 0); - drm_WARN_ON(&i915->drm, - (intel_de_read(i915, G4X_AUD_CNTL_ST) & G4X_ELD_ADDRESS_MASK) != 0); + drm_WARN_ON(display->drm, + (intel_de_read(display, G4X_AUD_CNTL_ST) & G4X_ELD_ADDRESS_MASK) != 0); - intel_de_rmw(i915, G4X_AUD_CNTL_ST, + intel_de_rmw(display, G4X_AUD_CNTL_ST, 0, G4X_ELD_VALID); } @@ -329,11 +329,11 @@ static void hsw_dp_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; /* Enable time stamps. Let HW calculate Maud/Naud values */ - intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), + intel_de_rmw(display, HSW_AUD_CFG(cpu_transcoder), AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK | AUD_CONFIG_UPPER_N_MASK | @@ -347,8 +347,8 @@ static void hsw_hdmi_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = i915->display.audio.component; + struct intel_display *display = to_intel_display(encoder); + struct i915_audio_component *acomp = display->audio.component; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum port port = encoder->port; int n, rate; @@ -356,7 +356,7 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder, rate = acomp ? acomp->aud_sample_rate[port] : 0; - tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder)); + tmp = intel_de_read(display, HSW_AUD_CFG(cpu_transcoder)); tmp &= ~AUD_CONFIG_N_VALUE_INDEX; tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; tmp &= ~AUD_CONFIG_N_PROG_ENABLE; @@ -364,25 +364,25 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder, n = audio_config_hdmi_get_n(crtc_state, rate); if (n != 0) { - drm_dbg_kms(&i915->drm, "using N %d\n", n); + drm_dbg_kms(display->drm, "using N %d\n", n); tmp &= ~AUD_CONFIG_N_MASK; tmp |= AUD_CONFIG_N(n); tmp |= AUD_CONFIG_N_PROG_ENABLE; } else { - drm_dbg_kms(&i915->drm, "using automatic N\n"); + drm_dbg_kms(display->drm, "using automatic N\n"); } - intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp); + intel_de_write(display, HSW_AUD_CFG(cpu_transcoder), tmp); /* * Let's disable "Enable CTS or M Prog bit" * and let HW calculate the value */ - tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); + tmp = intel_de_read(display, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); tmp &= ~AUD_M_CTS_M_PROG_ENABLE; tmp &= ~AUD_M_CTS_M_VALUE_INDEX; - intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); + intel_de_write(display, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); } static void @@ -399,14 +399,14 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); /* Disable timestamps */ - intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), + intel_de_rmw(display, HSW_AUD_CFG(cpu_transcoder), AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK, @@ -415,26 +415,26 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, AUD_CONFIG_N_VALUE_INDEX : 0)); /* Invalidate ELD */ - intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + intel_de_rmw(display, HSW_AUD_PIN_ELD_CP_VLD, AUDIO_ELD_VALID(cpu_transcoder), 0); intel_crtc_wait_for_next_vblank(crtc); intel_crtc_wait_for_next_vblank(crtc); /* Disable audio presence detect */ - intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + intel_de_rmw(display, HSW_AUD_PIN_ELD_CP_VLD, AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0); - if (needs_wa_14020863754(i915)) - intel_de_rmw(i915, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0); + if (needs_wa_14020863754(display)) + intel_de_rmw(display, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0); - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); } static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); unsigned int link_clks_available, link_clks_required; unsigned int tu_data, tu_line, link_clks_active; unsigned int h_active, h_total, hblank_delta, pixel_clk; @@ -446,13 +446,13 @@ static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder, h_total = crtc_state->hw.adjusted_mode.crtc_htotal; pixel_clk = crtc_state->hw.adjusted_mode.crtc_clock; vdsc_bppx16 = crtc_state->dsc.compressed_bpp_x16; - cdclk = i915->display.cdclk.hw.cdclk; + cdclk = display->cdclk.hw.cdclk; /* fec= 0.972261, using rounding multiplier of 1000000 */ fec_coeff = 972261; link_clk = crtc_state->port_clock; lanes = crtc_state->lane_count; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "h_active = %u link_clk = %u : lanes = %u vdsc_bpp = " FXP_Q4_FMT " cdclk = %u\n", h_active, link_clk, lanes, FXP_Q4_ARGS(vdsc_bppx16), cdclk); @@ -497,19 +497,19 @@ static unsigned int calc_samples_room(const struct intel_crtc_state *crtc_state) static void enable_audio_dsc_wa(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; unsigned int hblank_early_prog, samples_room; unsigned int val; - if (DISPLAY_VER(i915) < 11) + if (DISPLAY_VER(display) < 11) return; - val = intel_de_read(i915, AUD_CONFIG_BE); + val = intel_de_read(display, AUD_CONFIG_BE); - if (DISPLAY_VER(i915) == 11) + if (DISPLAY_VER(display) == 11) val |= HBLANK_EARLY_ENABLE_ICL(cpu_transcoder); - else if (DISPLAY_VER(i915) >= 12) + else if (DISPLAY_VER(display) >= 12) val |= HBLANK_EARLY_ENABLE_TGL(cpu_transcoder); if (crtc_state->dsc.compression_enable && @@ -536,34 +536,34 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder, val |= NUMBER_SAMPLES_PER_LINE(cpu_transcoder, 0x0); } - intel_de_write(i915, AUD_CONFIG_BE, val); + intel_de_write(display, AUD_CONFIG_BE, val); } static void hsw_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); /* Enable Audio WA for 4k DSC usecases */ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) enable_audio_dsc_wa(encoder, crtc_state); - if (needs_wa_14020863754(i915)) - intel_de_rmw(i915, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX); + if (needs_wa_14020863754(display)) + intel_de_rmw(display, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX); /* Enable audio presence detect */ - intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + intel_de_rmw(display, HSW_AUD_PIN_ELD_CP_VLD, 0, AUDIO_OUTPUT_ENABLE(cpu_transcoder)); intel_crtc_wait_for_next_vblank(crtc); /* Invalidate ELD */ - intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, + intel_de_rmw(display, HSW_AUD_PIN_ELD_CP_VLD, AUDIO_ELD_VALID(cpu_transcoder), 0); /* @@ -574,18 +574,20 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, /* Enable timestamps */ hsw_audio_config_update(encoder, crtc_state); - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); } struct ibx_audio_regs { i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; }; -static void ibx_audio_regs_init(struct drm_i915_private *i915, +static void ibx_audio_regs_init(struct intel_display *display, enum pipe pipe, struct ibx_audio_regs *regs) { - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + struct drm_i915_private *i915 = to_i915(display->drm); + + if (display->platform.valleyview || display->platform.cherryview) { regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); regs->aud_config = VLV_AUD_CFG(pipe); regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe); @@ -607,21 +609,21 @@ static void ibx_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum port port = encoder->port; enum pipe pipe = crtc->pipe; struct ibx_audio_regs regs; - if (drm_WARN_ON(&i915->drm, port == PORT_A)) + if (drm_WARN_ON(display->drm, port == PORT_A)) return; - ibx_audio_regs_init(i915, pipe, ®s); + ibx_audio_regs_init(display, pipe, ®s); - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); /* Disable timestamps */ - intel_de_rmw(i915, regs.aud_config, + intel_de_rmw(display, regs.aud_config, AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK, @@ -630,10 +632,10 @@ static void ibx_audio_codec_disable(struct intel_encoder *encoder, AUD_CONFIG_N_VALUE_INDEX : 0)); /* Invalidate ELD */ - intel_de_rmw(i915, regs.aud_cntrl_st2, + intel_de_rmw(display, regs.aud_cntrl_st2, IBX_ELD_VALID(port), 0); - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); intel_crtc_wait_for_next_vblank(crtc); intel_crtc_wait_for_next_vblank(crtc); @@ -643,23 +645,23 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum port port = encoder->port; enum pipe pipe = crtc->pipe; struct ibx_audio_regs regs; - if (drm_WARN_ON(&i915->drm, port == PORT_A)) + if (drm_WARN_ON(display->drm, port == PORT_A)) return; intel_crtc_wait_for_next_vblank(crtc); - ibx_audio_regs_init(i915, pipe, ®s); + ibx_audio_regs_init(display, pipe, ®s); - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); /* Invalidate ELD */ - intel_de_rmw(i915, regs.aud_cntrl_st2, + intel_de_rmw(display, regs.aud_cntrl_st2, IBX_ELD_VALID(port), 0); /* @@ -668,7 +670,7 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder, */ /* Enable timestamps */ - intel_de_rmw(i915, regs.aud_config, + intel_de_rmw(display, regs.aud_config, AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE | AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, @@ -676,7 +678,7 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder, AUD_CONFIG_N_VALUE_INDEX : audio_config_hdmi_pixel_clock(crtc_state))); - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); } void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state) @@ -693,14 +695,14 @@ bool intel_audio_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct drm_connector *connector = conn_state->connector; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; mutex_lock(&connector->eld_mutex); if (!connector->eld[0]) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "Bogus ELD on [CONNECTOR:%d:%s]\n", connector->base.id, connector->name); mutex_unlock(&connector->eld_mutex); @@ -729,8 +731,9 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = i915->display.audio.component; + struct i915_audio_component *acomp = display->audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_connector *connector = to_intel_connector(conn_state->connector); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -740,26 +743,27 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, if (!crtc_state->has_audio) return; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on [CRTC:%d:%s], %u bytes ELD\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on [CRTC:%d:%s], %u bytes ELD\n", connector->base.base.id, connector->base.name, encoder->base.base.id, encoder->base.name, crtc->base.base.id, crtc->base.name, drm_eld_size(crtc_state->eld)); - if (i915->display.funcs.audio) - i915->display.funcs.audio->audio_codec_enable(encoder, + if (display->funcs.audio) + display->funcs.audio->audio_codec_enable(encoder, crtc_state, conn_state); - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); - audio_state = &i915->display.audio.state[cpu_transcoder]; + audio_state = &display->audio.state[cpu_transcoder]; audio_state->encoder = encoder; BUILD_BUG_ON(sizeof(audio_state->eld) != sizeof(crtc_state->eld)); memcpy(audio_state->eld, crtc_state->eld, sizeof(audio_state->eld)); - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -788,8 +792,9 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = i915->display.audio.component; + struct i915_audio_component *acomp = display->audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct intel_connector *connector = to_intel_connector(old_conn_state->connector); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; @@ -799,24 +804,25 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, if (!old_crtc_state->has_audio) return; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on [CRTC:%d:%s]\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on [CRTC:%d:%s]\n", connector->base.base.id, connector->base.name, encoder->base.base.id, encoder->base.name, crtc->base.base.id, crtc->base.name); - if (i915->display.funcs.audio) - i915->display.funcs.audio->audio_codec_disable(encoder, + if (display->funcs.audio) + display->funcs.audio->audio_codec_disable(encoder, old_crtc_state, old_conn_state); - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); - audio_state = &i915->display.audio.state[cpu_transcoder]; + audio_state = &display->audio.state[cpu_transcoder]; audio_state->encoder = NULL; memset(audio_state->eld, 0, sizeof(audio_state->eld)); - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -833,30 +839,30 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, static void intel_acomp_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; struct intel_audio_state *audio_state; - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); - audio_state = &i915->display.audio.state[cpu_transcoder]; + audio_state = &display->audio.state[cpu_transcoder]; if (audio_state->encoder) memcpy(crtc_state->eld, audio_state->eld, sizeof(audio_state->eld)); - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); } void intel_audio_codec_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); if (!crtc_state->has_audio) return; - if (i915->display.funcs.audio) - i915->display.funcs.audio->audio_codec_get_config(encoder, crtc_state); + if (display->funcs.audio) + display->funcs.audio->audio_codec_get_config(encoder, crtc_state); } static const struct intel_audio_funcs g4x_audio_funcs = { @@ -879,17 +885,19 @@ static const struct intel_audio_funcs hsw_audio_funcs = { /** * intel_audio_hooks_init - Set up chip specific audio hooks - * @i915: device private + * @display: display device */ -void intel_audio_hooks_init(struct drm_i915_private *i915) +void intel_audio_hooks_init(struct intel_display *display) { - if (IS_G4X(i915)) - i915->display.funcs.audio = &g4x_audio_funcs; - else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915) || + struct drm_i915_private *i915 = to_i915(display->drm); + + if (display->platform.g4x) + display->funcs.audio = &g4x_audio_funcs; + else if (display->platform.valleyview || display->platform.cherryview || HAS_PCH_CPT(i915) || HAS_PCH_IBX(i915)) - i915->display.funcs.audio = &ibx_audio_funcs; - else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8) - i915->display.funcs.audio = &hsw_audio_funcs; + display->funcs.audio = &ibx_audio_funcs; + else if (display->platform.haswell || DISPLAY_VER(display) >= 8) + display->funcs.audio = &hsw_audio_funcs; } struct aud_ts_cdclk_m_n { @@ -897,10 +905,10 @@ struct aud_ts_cdclk_m_n { u16 n; }; -void intel_audio_cdclk_change_pre(struct drm_i915_private *i915) +void intel_audio_cdclk_change_pre(struct intel_display *display) { - if (DISPLAY_VER(i915) >= 13) - intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0); + if (DISPLAY_VER(display) >= 13) + intel_de_rmw(display, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0); } static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n *aud_ts) @@ -909,16 +917,18 @@ static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n aud_ts->n = cdclk * aud_ts->m / 24000; } -void intel_audio_cdclk_change_post(struct drm_i915_private *i915) +void intel_audio_cdclk_change_post(struct intel_display *display) { struct aud_ts_cdclk_m_n aud_ts; - if (DISPLAY_VER(i915) >= 13) { - get_aud_ts_cdclk_m_n(i915->display.cdclk.hw.ref, i915->display.cdclk.hw.cdclk, &aud_ts); + if (DISPLAY_VER(display) >= 13) { + get_aud_ts_cdclk_m_n(display->cdclk.hw.ref, + display->cdclk.hw.cdclk, &aud_ts); - intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n); - intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN); - drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n", aud_ts.m, aud_ts.n); + intel_de_write(display, AUD_TS_CDCLK_N, aud_ts.n); + intel_de_write(display, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN); + drm_dbg_kms(display->drm, "aud_ts_cdclk set to M=%u, N=%u\n", + aud_ts.m, aud_ts.n); } } @@ -943,9 +953,10 @@ static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state, return drm_atomic_commit(&state->base); } -static void glk_force_audio_cdclk(struct drm_i915_private *i915, +static void glk_force_audio_cdclk(struct intel_display *display, bool enable) { + struct drm_i915_private *i915 = to_i915(display->drm); struct drm_modeset_acquire_ctx ctx; struct drm_atomic_state *state; struct intel_crtc *crtc; @@ -956,8 +967,8 @@ static void glk_force_audio_cdclk(struct drm_i915_private *i915, return; drm_modeset_acquire_init(&ctx, 0); - state = drm_atomic_state_alloc(&i915->drm); - if (drm_WARN_ON(&i915->drm, !state)) + state = drm_atomic_state_alloc(display->drm); + if (drm_WARN_ON(display->drm, !state)) return; state->acquire_ctx = &ctx; @@ -972,7 +983,7 @@ retry: goto retry; } - drm_WARN_ON(&i915->drm, ret); + drm_WARN_ON(display->drm, ret); drm_atomic_state_put(state); @@ -983,7 +994,6 @@ retry: int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - struct drm_i915_private *dev_priv = to_i915(display->drm); int min_cdclk = 0; if (!crtc_state->has_audio) @@ -1000,7 +1010,7 @@ int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state) if (DISPLAY_VER(display) == 10) { /* Display WA #1145: glk */ min_cdclk = max(min_cdclk, 316800); - } else if (DISPLAY_VER(display) == 9 || IS_BROADWELL(dev_priv)) { + } else if (DISPLAY_VER(display) == 9 || display->platform.broadwell) { /* Display WA #1144: skl,bxt */ min_cdclk = max(min_cdclk, 432000); } @@ -1020,7 +1030,7 @@ int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state) * 270 | 320 or higher * 162 | 200 or higher" */ - if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && + if ((display->platform.valleyview || display->platform.cherryview) && intel_crtc_has_dp_encoder(crtc_state)) min_cdclk = max(min_cdclk, crtc_state->port_clock); @@ -1038,21 +1048,21 @@ static unsigned long i915_audio_component_get_power(struct device *kdev) wakeref = intel_display_power_get(i915, POWER_DOMAIN_AUDIO_PLAYBACK); - if (i915->display.audio.power_refcount++ == 0) { - if (DISPLAY_VER(i915) >= 9) { - intel_de_write(i915, AUD_FREQ_CNTRL, - i915->display.audio.freq_cntrl); - drm_dbg_kms(&i915->drm, + if (display->audio.power_refcount++ == 0) { + if (DISPLAY_VER(display) >= 9) { + intel_de_write(display, AUD_FREQ_CNTRL, + display->audio.freq_cntrl); + drm_dbg_kms(display->drm, "restored AUD_FREQ_CNTRL to 0x%x\n", - i915->display.audio.freq_cntrl); + display->audio.freq_cntrl); } /* Force CDCLK to 2*BCLK as long as we need audio powered. */ - if (IS_GEMINILAKE(i915)) - glk_force_audio_cdclk(i915, true); + if (display->platform.geminilake) + glk_force_audio_cdclk(display, true); - if (DISPLAY_VER(i915) >= 10) - intel_de_rmw(i915, AUD_PIN_BUF_CTL, + if (DISPLAY_VER(display) >= 10) + intel_de_rmw(display, AUD_PIN_BUF_CTL, 0, AUD_PIN_BUF_ENABLE); } @@ -1067,9 +1077,9 @@ static void i915_audio_component_put_power(struct device *kdev, intel_wakeref_t wakeref = (intel_wakeref_t)cookie; /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */ - if (--i915->display.audio.power_refcount == 0) - if (IS_GEMINILAKE(i915)) - glk_force_audio_cdclk(i915, false); + if (--display->audio.power_refcount == 0) + if (display->platform.geminilake) + glk_force_audio_cdclk(display, false); intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, wakeref); } @@ -1078,10 +1088,9 @@ static void i915_audio_component_codec_wake_override(struct device *kdev, bool enable) { struct intel_display *display = to_intel_display(kdev); - struct drm_i915_private *i915 = to_i915(display->drm); unsigned long cookie; - if (DISPLAY_VER(i915) < 9) + if (DISPLAY_VER(display) < 9) return; cookie = i915_audio_component_get_power(kdev); @@ -1090,12 +1099,12 @@ static void i915_audio_component_codec_wake_override(struct device *kdev, * Enable/disable generating the codec wake signal, overriding the * internal logic to generate the codec wake to controller. */ - intel_de_rmw(i915, HSW_AUD_CHICKENBIT, + intel_de_rmw(display, HSW_AUD_CHICKENBIT, SKL_AUD_CODEC_WAKE_SIGNAL, 0); usleep_range(1000, 1500); if (enable) { - intel_de_rmw(i915, HSW_AUD_CHICKENBIT, + intel_de_rmw(display, HSW_AUD_CHICKENBIT, 0, SKL_AUD_CODEC_WAKE_SIGNAL); usleep_range(1000, 1500); } @@ -1107,12 +1116,11 @@ static void i915_audio_component_codec_wake_override(struct device *kdev, static int i915_audio_component_get_cdclk_freq(struct device *kdev) { struct intel_display *display = to_intel_display(kdev); - struct drm_i915_private *i915 = to_i915(display->drm); - if (drm_WARN_ON_ONCE(&i915->drm, !HAS_DDI(i915))) + if (drm_WARN_ON_ONCE(display->drm, !HAS_DDI(display))) return -ENODEV; - return i915->display.cdclk.hw.cdclk; + return display->cdclk.hw.cdclk; } /* @@ -1124,7 +1132,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) * will get the right intel_encoder with port matched * Non-MST & (cpu_transcoder < 0): get the right intel_encoder with port matched */ -static struct intel_audio_state *find_audio_state(struct drm_i915_private *i915, +static struct intel_audio_state *find_audio_state(struct intel_display *display, int port, int cpu_transcoder) { /* MST */ @@ -1132,11 +1140,11 @@ static struct intel_audio_state *find_audio_state(struct drm_i915_private *i915, struct intel_audio_state *audio_state; struct intel_encoder *encoder; - if (drm_WARN_ON(&i915->drm, - cpu_transcoder >= ARRAY_SIZE(i915->display.audio.state))) + if (drm_WARN_ON(display->drm, + cpu_transcoder >= ARRAY_SIZE(display->audio.state))) return NULL; - audio_state = &i915->display.audio.state[cpu_transcoder]; + audio_state = &display->audio.state[cpu_transcoder]; encoder = audio_state->encoder; if (encoder && encoder->port == port && @@ -1148,11 +1156,11 @@ static struct intel_audio_state *find_audio_state(struct drm_i915_private *i915, if (cpu_transcoder > 0) return NULL; - for_each_cpu_transcoder(i915, cpu_transcoder) { + for_each_cpu_transcoder(display, cpu_transcoder) { struct intel_audio_state *audio_state; struct intel_encoder *encoder; - audio_state = &i915->display.audio.state[cpu_transcoder]; + audio_state = &display->audio.state[cpu_transcoder]; encoder = audio_state->encoder; if (encoder && encoder->port == port && @@ -1167,23 +1175,23 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, int cpu_transcoder, int rate) { struct intel_display *display = to_intel_display(kdev); - struct drm_i915_private *i915 = to_i915(display->drm); - struct i915_audio_component *acomp = i915->display.audio.component; + struct i915_audio_component *acomp = display->audio.component; const struct intel_audio_state *audio_state; struct intel_encoder *encoder; struct intel_crtc *crtc; unsigned long cookie; int err = 0; - if (!HAS_DDI(i915)) + if (!HAS_DDI(display)) return 0; cookie = i915_audio_component_get_power(kdev); - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); - audio_state = find_audio_state(i915, port, cpu_transcoder); + audio_state = find_audio_state(display, port, cpu_transcoder); if (!audio_state) { - drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); + drm_dbg_kms(display->drm, "Not valid for port %c\n", + port_name(port)); err = -ENODEV; goto unlock; } @@ -1200,7 +1208,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, hsw_audio_config_update(encoder, crtc->config); unlock: - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); i915_audio_component_put_power(kdev, cookie); return err; } @@ -1210,16 +1218,16 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, unsigned char *buf, int max_bytes) { struct intel_display *display = to_intel_display(kdev); - struct drm_i915_private *i915 = to_i915(display->drm); const struct intel_audio_state *audio_state; int ret = 0; - mutex_lock(&i915->display.audio.mutex); + mutex_lock(&display->audio.mutex); - audio_state = find_audio_state(i915, port, cpu_transcoder); + audio_state = find_audio_state(display, port, cpu_transcoder); if (!audio_state) { - drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); - mutex_unlock(&i915->display.audio.mutex); + drm_dbg_kms(display->drm, "Not valid for port %c\n", + port_name(port)); + mutex_unlock(&display->audio.mutex); return -EINVAL; } @@ -1231,7 +1239,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, memcpy(buf, eld, min(max_bytes, ret)); } - mutex_unlock(&i915->display.audio.mutex); + mutex_unlock(&display->audio.mutex); return ret; } @@ -1249,26 +1257,25 @@ static int i915_audio_component_bind(struct device *drv_kdev, struct device *hda_kdev, void *data) { struct intel_display *display = to_intel_display(drv_kdev); - struct drm_i915_private *i915 = to_i915(display->drm); struct i915_audio_component *acomp = data; int i; - if (drm_WARN_ON(&i915->drm, acomp->base.ops || acomp->base.dev)) + if (drm_WARN_ON(display->drm, acomp->base.ops || acomp->base.dev)) return -EEXIST; - if (drm_WARN_ON(&i915->drm, + if (drm_WARN_ON(display->drm, !device_link_add(hda_kdev, drv_kdev, DL_FLAG_STATELESS))) return -ENOMEM; - drm_modeset_lock_all(&i915->drm); + drm_modeset_lock_all(display->drm); acomp->base.ops = &i915_audio_component_ops; acomp->base.dev = drv_kdev; BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) acomp->aud_sample_rate[i] = 0; - i915->display.audio.component = acomp; - drm_modeset_unlock_all(&i915->drm); + display->audio.component = acomp; + drm_modeset_unlock_all(display->drm); return 0; } @@ -1277,20 +1284,20 @@ static void i915_audio_component_unbind(struct device *drv_kdev, struct device *hda_kdev, void *data) { struct intel_display *display = to_intel_display(drv_kdev); - struct drm_i915_private *i915 = to_i915(display->drm); struct i915_audio_component *acomp = data; - drm_modeset_lock_all(&i915->drm); + drm_modeset_lock_all(display->drm); acomp->base.ops = NULL; acomp->base.dev = NULL; - i915->display.audio.component = NULL; - drm_modeset_unlock_all(&i915->drm); + display->audio.component = NULL; + drm_modeset_unlock_all(display->drm); device_link_remove(hda_kdev, drv_kdev); - if (i915->display.audio.power_refcount) - drm_err(&i915->drm, "audio power refcount %d after unbind\n", - i915->display.audio.power_refcount); + if (display->audio.power_refcount) + drm_err(display->drm, + "audio power refcount %d after unbind\n", + display->audio.power_refcount); } static const struct component_ops i915_audio_component_bind_ops = { @@ -1309,7 +1316,7 @@ static const struct component_ops i915_audio_component_bind_ops = { /** * i915_audio_component_init - initialize and register the audio component - * @i915: i915 device instance + * @display: display device * * This will register with the component framework a child component which * will bind dynamically to the snd_hda_intel driver's corresponding master @@ -1323,93 +1330,97 @@ static const struct component_ops i915_audio_component_bind_ops = { * We ignore any error during registration and continue with reduced * functionality (i.e. without HDMI audio). */ -static void i915_audio_component_init(struct drm_i915_private *i915) +static void i915_audio_component_init(struct intel_display *display) { u32 aud_freq, aud_freq_init; - if (DISPLAY_VER(i915) >= 9) { - aud_freq_init = intel_de_read(i915, AUD_FREQ_CNTRL); + if (DISPLAY_VER(display) >= 9) { + aud_freq_init = intel_de_read(display, AUD_FREQ_CNTRL); - if (DISPLAY_VER(i915) >= 12) + if (DISPLAY_VER(display) >= 12) aud_freq = AUD_FREQ_GEN12; else aud_freq = aud_freq_init; /* use BIOS provided value for TGL and RKL unless it is a known bad value */ - if ((IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915)) && + if ((display->platform.tigerlake || display->platform.rocketlake) && aud_freq_init != AUD_FREQ_TGL_BROKEN) aud_freq = aud_freq_init; - drm_dbg_kms(&i915->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", + drm_dbg_kms(display->drm, + "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", aud_freq, aud_freq_init); - i915->display.audio.freq_cntrl = aud_freq; + display->audio.freq_cntrl = aud_freq; } /* init with current cdclk */ - intel_audio_cdclk_change_post(i915); + intel_audio_cdclk_change_post(display); } -static void i915_audio_component_register(struct drm_i915_private *i915) +static void i915_audio_component_register(struct intel_display *display) { int ret; - ret = component_add_typed(i915->drm.dev, + ret = component_add_typed(display->drm->dev, &i915_audio_component_bind_ops, I915_COMPONENT_AUDIO); if (ret < 0) { - drm_err(&i915->drm, + drm_err(display->drm, "failed to add audio component (%d)\n", ret); /* continue with reduced functionality */ return; } - i915->display.audio.component_registered = true; + display->audio.component_registered = true; } /** * i915_audio_component_cleanup - deregister the audio component - * @i915: i915 device instance + * @display: display device * * Deregisters the audio component, breaking any existing binding to the * corresponding snd_hda_intel driver's master component. */ -static void i915_audio_component_cleanup(struct drm_i915_private *i915) +static void i915_audio_component_cleanup(struct intel_display *display) { - if (!i915->display.audio.component_registered) + if (!display->audio.component_registered) return; - component_del(i915->drm.dev, &i915_audio_component_bind_ops); - i915->display.audio.component_registered = false; + component_del(display->drm->dev, &i915_audio_component_bind_ops); + display->audio.component_registered = false; } /** * intel_audio_init() - Initialize the audio driver either using * component framework or using lpe audio bridge - * @i915: the i915 drm device private data + * @display: display device * */ -void intel_audio_init(struct drm_i915_private *i915) +void intel_audio_init(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + if (intel_lpe_audio_init(i915) < 0) - i915_audio_component_init(i915); + i915_audio_component_init(display); } -void intel_audio_register(struct drm_i915_private *i915) +void intel_audio_register(struct intel_display *display) { - if (!i915->display.audio.lpe.platdev) - i915_audio_component_register(i915); + if (!display->audio.lpe.platdev) + i915_audio_component_register(display); } /** * intel_audio_deinit() - deinitialize the audio driver - * @i915: the i915 drm device private data - * + * @display: display device */ -void intel_audio_deinit(struct drm_i915_private *i915) +void intel_audio_deinit(struct intel_display *display) { - if (i915->display.audio.lpe.platdev != NULL) + struct drm_i915_private *i915 = to_i915(display->drm); + + if (display->audio.lpe.platdev) intel_lpe_audio_teardown(i915); else - i915_audio_component_cleanup(i915); + i915_audio_component_cleanup(display); } diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index 1bafc155434a..ad49eefa7182 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -9,11 +9,11 @@ #include struct drm_connector_state; -struct drm_i915_private; struct intel_crtc_state; +struct intel_display; struct intel_encoder; -void intel_audio_hooks_init(struct drm_i915_private *dev_priv); +void intel_audio_hooks_init(struct intel_display *display); bool intel_audio_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state); @@ -25,12 +25,12 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state); void intel_audio_codec_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state); -void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv); -void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv); +void intel_audio_cdclk_change_pre(struct intel_display *display); +void intel_audio_cdclk_change_post(struct intel_display *display); int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state); -void intel_audio_init(struct drm_i915_private *dev_priv); -void intel_audio_register(struct drm_i915_private *i915); -void intel_audio_deinit(struct drm_i915_private *dev_priv); +void intel_audio_init(struct intel_display *display); +void intel_audio_register(struct intel_display *display); +void intel_audio_deinit(struct intel_display *display); void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_AUDIO_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index c7a603589412..bee90b06995a 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2521,7 +2521,6 @@ static void intel_set_cdclk(struct intel_display *display, const struct intel_cdclk_config *cdclk_config, enum pipe pipe, const char *context) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_encoder *encoder; if (!intel_cdclk_changed(&display->cdclk.hw, cdclk_config)) @@ -2538,7 +2537,7 @@ static void intel_set_cdclk(struct intel_display *display, intel_psr_pause(intel_dp); } - intel_audio_cdclk_change_pre(dev_priv); + intel_audio_cdclk_change_pre(display); /* * Lock aux/gmbus while we change cdclk in case those @@ -2568,7 +2567,7 @@ static void intel_set_cdclk(struct intel_display *display, intel_psr_resume(intel_dp); } - intel_audio_cdclk_change_post(dev_priv); + intel_audio_cdclk_change_post(display); if (drm_WARN(display->drm, intel_cdclk_changed(&display->cdclk.hw, cdclk_config), diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 1aa0b298c278..73ea0e906014 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -197,7 +197,7 @@ void intel_display_driver_early_probe(struct intel_display *display) intel_dkl_phy_init(i915); intel_color_init_hooks(display); intel_init_cdclk_hooks(display); - intel_audio_hooks_init(i915); + intel_audio_hooks_init(display); intel_dpll_init_clock_hook(i915); intel_init_display_hooks(i915); intel_fdi_init_hook(i915); @@ -546,11 +546,11 @@ void intel_display_driver_register(struct intel_display *display) intel_opregion_register(display); intel_acpi_video_register(display); - intel_audio_init(i915); + intel_audio_init(display); intel_display_driver_enable_user_access(display); - intel_audio_register(i915); + intel_audio_register(display); intel_display_debugfs_register(i915); @@ -638,8 +638,6 @@ void intel_display_driver_remove_nogem(struct intel_display *display) void intel_display_driver_unregister(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - if (!HAS_DISPLAY(display)) return; @@ -654,7 +652,7 @@ void intel_display_driver_unregister(struct intel_display *display) intel_display_driver_disable_user_access(display); - intel_audio_deinit(i915); + intel_audio_deinit(display); drm_atomic_helper_shutdown(display->drm); diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index b3921dbc52ff..96ba9595bf2a 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -216,7 +216,7 @@ void xe_display_fini(struct xe_device *xe) intel_hpd_poll_fini(xe); intel_hdcp_component_fini(display); - intel_audio_deinit(xe); + intel_audio_deinit(display); } void xe_display_register(struct xe_device *xe) -- cgit v1.2.3-59-g8ed1b From 2b85c4feeeb73984dc676f7fdbcff71e82a1dbab Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 8 Jan 2025 16:04:14 +0200 Subject: drm/i915/audio: convert LPE audio to struct intel_display Going forward, struct intel_display will be the main display device structure. Convert intel_lpe_audio.[ch] to it. Do some minor checkpatch fixes while at it. TODO: Not sure if irq_set_chip_data(irq, dev_priv); is used. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/f04dd028cd8869cdfb9ab9eb6aceed8ff8e7ddcd.1736345025.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_audio.c | 14 +-- drivers/gpu/drm/i915/display/intel_lpe_audio.c | 118 +++++++++++++------------ drivers/gpu/drm/i915/display/intel_lpe_audio.h | 18 ++-- drivers/gpu/drm/i915/i915_irq.c | 6 +- 4 files changed, 77 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 8c26e0e7c2cd..241e5d3904dc 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -732,7 +732,6 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct i915_audio_component *acomp = display->audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_connector *connector = to_intel_connector(conn_state->connector); @@ -774,7 +773,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, (int)port, (int)cpu_transcoder); } - intel_lpe_audio_notify(i915, cpu_transcoder, port, crtc_state->eld, + intel_lpe_audio_notify(display, cpu_transcoder, port, crtc_state->eld, crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state)); } @@ -793,7 +792,6 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct i915_audio_component *acomp = display->audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct intel_connector *connector = to_intel_connector(old_conn_state->connector); @@ -833,7 +831,7 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, (int)port, (int)cpu_transcoder); } - intel_lpe_audio_notify(i915, cpu_transcoder, port, NULL, 0, false); + intel_lpe_audio_notify(display, cpu_transcoder, port, NULL, 0, false); } static void intel_acomp_get_config(struct intel_encoder *encoder, @@ -1399,9 +1397,7 @@ static void i915_audio_component_cleanup(struct intel_display *display) */ void intel_audio_init(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - if (intel_lpe_audio_init(i915) < 0) + if (intel_lpe_audio_init(display) < 0) i915_audio_component_init(display); } @@ -1417,10 +1413,8 @@ void intel_audio_register(struct intel_display *display) */ void intel_audio_deinit(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - if (display->audio.lpe.platdev) - intel_lpe_audio_teardown(i915); + intel_lpe_audio_teardown(display); else i915_audio_component_cleanup(display); } diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index f11626176fe2..59551c8414c2 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -77,12 +77,12 @@ #include "intel_lpe_audio.h" #include "intel_pci_config.h" -#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->display.audio.lpe.platdev != NULL) +#define HAS_LPE_AUDIO(display) ((display)->audio.lpe.platdev) static struct platform_device * -lpe_audio_platdev_create(struct drm_i915_private *dev_priv) +lpe_audio_platdev_create(struct intel_display *display) { - struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct pci_dev *pdev = to_pci_dev(display->drm->dev); struct platform_device_info pinfo = {}; struct resource *rsc; struct platform_device *platdev; @@ -98,7 +98,8 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) return ERR_PTR(-ENOMEM); } - rsc[0].start = rsc[0].end = dev_priv->display.audio.lpe.irq; + rsc[0].start = display->audio.lpe.irq; + rsc[0].end = display->audio.lpe.irq; rsc[0].flags = IORESOURCE_IRQ; rsc[0].name = "hdmi-lpe-audio-irq"; @@ -109,7 +110,7 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) rsc[1].flags = IORESOURCE_MEM; rsc[1].name = "hdmi-lpe-audio-mmio"; - pinfo.parent = dev_priv->drm.dev; + pinfo.parent = display->drm->dev; pinfo.name = "hdmi-lpe-audio"; pinfo.id = -1; pinfo.res = rsc; @@ -118,8 +119,8 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) pinfo.size_data = sizeof(*pdata); pinfo.dma_mask = DMA_BIT_MASK(32); - pdata->num_pipes = INTEL_NUM_PIPES(dev_priv); - pdata->num_ports = IS_CHERRYVIEW(dev_priv) ? 3 : 2; /* B,C,D or B,C */ + pdata->num_pipes = INTEL_NUM_PIPES(display); + pdata->num_ports = display->platform.cherryview ? 3 : 2; /* B,C,D or B,C */ pdata->port[0].pipe = -1; pdata->port[1].pipe = -1; pdata->port[2].pipe = -1; @@ -130,7 +131,7 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) kfree(pdata); if (IS_ERR(platdev)) { - drm_err(&dev_priv->drm, + drm_err(display->drm, "Failed to allocate LPE audio platform device\n"); return platdev; } @@ -140,7 +141,7 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) return platdev; } -static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) +static void lpe_audio_platdev_destroy(struct intel_display *display) { /* XXX Note that platform_device_register_full() allocates a dma_mask * and never frees it. We can't free it here as we cannot guarantee @@ -150,7 +151,7 @@ static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) * than us fiddle with its internals. */ - platform_device_unregister(dev_priv->display.audio.lpe.platdev); + platform_device_unregister(display->audio.lpe.platdev); } static void lpe_audio_irq_unmask(struct irq_data *d) @@ -167,11 +168,12 @@ static struct irq_chip lpe_audio_irqchip = { .irq_unmask = lpe_audio_irq_unmask, }; -static int lpe_audio_irq_init(struct drm_i915_private *dev_priv) +static int lpe_audio_irq_init(struct intel_display *display) { - int irq = dev_priv->display.audio.lpe.irq; + struct drm_i915_private *dev_priv = to_i915(display->drm); + int irq = display->audio.lpe.irq; - drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); + drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)); irq_set_chip_and_handler_name(irq, &lpe_audio_irqchip, handle_simple_irq, @@ -180,11 +182,11 @@ static int lpe_audio_irq_init(struct drm_i915_private *dev_priv) return irq_set_chip_data(irq, dev_priv); } -static bool lpe_audio_detect(struct drm_i915_private *dev_priv) +static bool lpe_audio_detect(struct intel_display *display) { int lpe_present = false; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + if (display->platform.valleyview || display->platform.cherryview) { static const struct pci_device_id atom_hdaudio_ids[] = { /* Baytrail */ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f04)}, @@ -194,7 +196,7 @@ static bool lpe_audio_detect(struct drm_i915_private *dev_priv) }; if (!pci_dev_present(atom_hdaudio_ids)) { - drm_info(&dev_priv->drm, + drm_info(display->drm, "HDaudio controller not detected, using LPE audio instead\n"); lpe_present = true; } @@ -202,34 +204,34 @@ static bool lpe_audio_detect(struct drm_i915_private *dev_priv) return lpe_present; } -static int lpe_audio_setup(struct drm_i915_private *dev_priv) +static int lpe_audio_setup(struct intel_display *display) { int ret; - dev_priv->display.audio.lpe.irq = irq_alloc_desc(0); - if (dev_priv->display.audio.lpe.irq < 0) { - drm_err(&dev_priv->drm, "Failed to allocate IRQ desc: %d\n", - dev_priv->display.audio.lpe.irq); - ret = dev_priv->display.audio.lpe.irq; + display->audio.lpe.irq = irq_alloc_desc(0); + if (display->audio.lpe.irq < 0) { + drm_err(display->drm, "Failed to allocate IRQ desc: %d\n", + display->audio.lpe.irq); + ret = display->audio.lpe.irq; goto err; } - drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->display.audio.lpe.irq); + drm_dbg(display->drm, "irq = %d\n", display->audio.lpe.irq); - ret = lpe_audio_irq_init(dev_priv); + ret = lpe_audio_irq_init(display); if (ret) { - drm_err(&dev_priv->drm, + drm_err(display->drm, "Failed to initialize irqchip for lpe audio: %d\n", ret); goto err_free_irq; } - dev_priv->display.audio.lpe.platdev = lpe_audio_platdev_create(dev_priv); + display->audio.lpe.platdev = lpe_audio_platdev_create(display); - if (IS_ERR(dev_priv->display.audio.lpe.platdev)) { - ret = PTR_ERR(dev_priv->display.audio.lpe.platdev); - drm_err(&dev_priv->drm, + if (IS_ERR(display->audio.lpe.platdev)) { + ret = PTR_ERR(display->audio.lpe.platdev); + drm_err(display->drm, "Failed to create lpe audio platform device: %d\n", ret); goto err_free_irq; @@ -238,54 +240,54 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv) /* enable chicken bit; at least this is required for Dell Wyse 3040 * with DP outputs (but only sometimes by some reason!) */ - intel_de_write(dev_priv, VLV_AUD_CHICKEN_BIT_REG, + intel_de_write(display, VLV_AUD_CHICKEN_BIT_REG, VLV_CHICKEN_BIT_DBG_ENABLE); return 0; err_free_irq: - irq_free_desc(dev_priv->display.audio.lpe.irq); + irq_free_desc(display->audio.lpe.irq); err: - dev_priv->display.audio.lpe.irq = -1; - dev_priv->display.audio.lpe.platdev = NULL; + display->audio.lpe.irq = -1; + display->audio.lpe.platdev = NULL; return ret; } /** * intel_lpe_audio_irq_handler() - forwards the LPE audio irq - * @dev_priv: the i915 drm device private data + * @display: display device * * the LPE Audio irq is forwarded to the irq handler registered by LPE audio * driver. */ -void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv) +void intel_lpe_audio_irq_handler(struct intel_display *display) { int ret; - if (!HAS_LPE_AUDIO(dev_priv)) + if (!HAS_LPE_AUDIO(display)) return; - ret = generic_handle_irq(dev_priv->display.audio.lpe.irq); + ret = generic_handle_irq(display->audio.lpe.irq); if (ret) - drm_err_ratelimited(&dev_priv->drm, + drm_err_ratelimited(display->drm, "error handling LPE audio irq: %d\n", ret); } /** * intel_lpe_audio_init() - detect and setup the bridge between HDMI LPE Audio * driver and i915 - * @dev_priv: the i915 drm device private data + * @display: display device * * Return: 0 if successful. non-zero if detection or * llocation/initialization fails */ -int intel_lpe_audio_init(struct drm_i915_private *dev_priv) +int intel_lpe_audio_init(struct intel_display *display) { int ret = -ENODEV; - if (lpe_audio_detect(dev_priv)) { - ret = lpe_audio_setup(dev_priv); + if (lpe_audio_detect(display)) { + ret = lpe_audio_setup(display); if (ret < 0) - drm_err(&dev_priv->drm, + drm_err(display->drm, "failed to setup LPE Audio bridge\n"); } return ret; @@ -294,27 +296,27 @@ int intel_lpe_audio_init(struct drm_i915_private *dev_priv) /** * intel_lpe_audio_teardown() - destroy the bridge between HDMI LPE * audio driver and i915 - * @dev_priv: the i915 drm device private data + * @display: display device * * release all the resources for LPE audio <-> i915 bridge. */ -void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv) +void intel_lpe_audio_teardown(struct intel_display *display) { - if (!HAS_LPE_AUDIO(dev_priv)) + if (!HAS_LPE_AUDIO(display)) return; - lpe_audio_platdev_destroy(dev_priv); + lpe_audio_platdev_destroy(display); - irq_free_desc(dev_priv->display.audio.lpe.irq); + irq_free_desc(display->audio.lpe.irq); - dev_priv->display.audio.lpe.irq = -1; - dev_priv->display.audio.lpe.platdev = NULL; + display->audio.lpe.irq = -1; + display->audio.lpe.platdev = NULL; } /** * intel_lpe_audio_notify() - notify lpe audio event * audio driver and i915 - * @dev_priv: the i915 drm device private data + * @display: display device * @cpu_transcoder: CPU transcoder * @port: port * @eld : ELD data @@ -323,7 +325,7 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv) * * Notify lpe audio driver of eld change. */ -void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, +void intel_lpe_audio_notify(struct intel_display *display, enum transcoder cpu_transcoder, enum port port, const void *eld, int ls_clock, bool dp_output) { @@ -332,15 +334,15 @@ void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, struct intel_hdmi_lpe_audio_port_pdata *ppdata; u32 audio_enable; - if (!HAS_LPE_AUDIO(dev_priv)) + if (!HAS_LPE_AUDIO(display)) return; - pdata = dev_get_platdata(&dev_priv->display.audio.lpe.platdev->dev); + pdata = dev_get_platdata(&display->audio.lpe.platdev->dev); ppdata = &pdata->port[port - PORT_B]; spin_lock_irqsave(&pdata->lpe_audio_slock, irqflags); - audio_enable = intel_de_read(dev_priv, VLV_AUD_PORT_EN_DBG(port)); + audio_enable = intel_de_read(display, VLV_AUD_PORT_EN_DBG(port)); if (eld != NULL) { memcpy(ppdata->eld, eld, HDMI_MAX_ELD_BYTES); @@ -349,7 +351,7 @@ void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, ppdata->dp_output = dp_output; /* Unmute the amp for both DP and HDMI */ - intel_de_write(dev_priv, VLV_AUD_PORT_EN_DBG(port), + intel_de_write(display, VLV_AUD_PORT_EN_DBG(port), audio_enable & ~VLV_AMP_MUTE); } else { memset(ppdata->eld, 0, HDMI_MAX_ELD_BYTES); @@ -358,12 +360,12 @@ void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, ppdata->dp_output = false; /* Mute the amp for both DP and HDMI */ - intel_de_write(dev_priv, VLV_AUD_PORT_EN_DBG(port), + intel_de_write(display, VLV_AUD_PORT_EN_DBG(port), audio_enable | VLV_AMP_MUTE); } if (pdata->notify_audio_lpe) - pdata->notify_audio_lpe(dev_priv->display.audio.lpe.platdev, port - PORT_B); + pdata->notify_audio_lpe(display->audio.lpe.platdev, port - PORT_B); spin_unlock_irqrestore(&pdata->lpe_audio_slock, irqflags); } diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.h b/drivers/gpu/drm/i915/display/intel_lpe_audio.h index 2c5fcb6e1fd0..5234e11fd662 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.h +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.h @@ -10,27 +10,27 @@ enum port; enum transcoder; -struct drm_i915_private; +struct intel_display; #ifdef I915 -int intel_lpe_audio_init(struct drm_i915_private *dev_priv); -void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv); -void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv); -void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, +int intel_lpe_audio_init(struct intel_display *display); +void intel_lpe_audio_teardown(struct intel_display *display); +void intel_lpe_audio_irq_handler(struct intel_display *display); +void intel_lpe_audio_notify(struct intel_display *display, enum transcoder cpu_transcoder, enum port port, const void *eld, int ls_clock, bool dp_output); #else -static inline int intel_lpe_audio_init(struct drm_i915_private *dev_priv) +static inline int intel_lpe_audio_init(struct intel_display *display) { return -ENODEV; } -static inline void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv) +static inline void intel_lpe_audio_teardown(struct intel_display *display) { } -static inline void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv) +static inline void intel_lpe_audio_irq_handler(struct intel_display *display) { } -static inline void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, +static inline void intel_lpe_audio_notify(struct intel_display *display, enum transcoder cpu_transcoder, enum port port, const void *eld, int ls_clock, bool dp_output) { diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7920ad9585ae..202eb1b6ae54 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -207,6 +207,7 @@ out: static irqreturn_t valleyview_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; + struct intel_display *display = &dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -260,7 +261,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) if (iir & (I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT)) - intel_lpe_audio_irq_handler(dev_priv); + intel_lpe_audio_irq_handler(display); /* * VLV_IIR is single buffered, and reflects the level @@ -293,6 +294,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) static irqreturn_t cherryview_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; + struct intel_display *display = &dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -343,7 +345,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) if (iir & (I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT | I915_LPE_PIPE_C_INTERRUPT)) - intel_lpe_audio_irq_handler(dev_priv); + intel_lpe_audio_irq_handler(display); /* * VLV_IIR is single buffered, and reflects the level -- cgit v1.2.3-59-g8ed1b From 90322277a3f1ddf5740aac703e92ef99c7a45f32 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 8 Jan 2025 16:04:15 +0200 Subject: drm/i915/audio: rename function prefixes from i915 to intel The intel prefix is more accurate for display stuff. Rename. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/5e67f6fc5a441a9512d7855d86ce7868cc992212.1736345025.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_audio.c | 82 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 241e5d3904dc..4b1f46815ad5 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -1035,7 +1035,7 @@ int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state) return min_cdclk; } -static unsigned long i915_audio_component_get_power(struct device *kdev) +static unsigned long intel_audio_component_get_power(struct device *kdev) { struct intel_display *display = to_intel_display(kdev); struct drm_i915_private *i915 = to_i915(display->drm); @@ -1067,8 +1067,8 @@ static unsigned long i915_audio_component_get_power(struct device *kdev) return (unsigned long)wakeref; } -static void i915_audio_component_put_power(struct device *kdev, - unsigned long cookie) +static void intel_audio_component_put_power(struct device *kdev, + unsigned long cookie) { struct intel_display *display = to_intel_display(kdev); struct drm_i915_private *i915 = to_i915(display->drm); @@ -1082,8 +1082,8 @@ static void i915_audio_component_put_power(struct device *kdev, intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, wakeref); } -static void i915_audio_component_codec_wake_override(struct device *kdev, - bool enable) +static void intel_audio_component_codec_wake_override(struct device *kdev, + bool enable) { struct intel_display *display = to_intel_display(kdev); unsigned long cookie; @@ -1091,7 +1091,7 @@ static void i915_audio_component_codec_wake_override(struct device *kdev, if (DISPLAY_VER(display) < 9) return; - cookie = i915_audio_component_get_power(kdev); + cookie = intel_audio_component_get_power(kdev); /* * Enable/disable generating the codec wake signal, overriding the @@ -1107,11 +1107,11 @@ static void i915_audio_component_codec_wake_override(struct device *kdev, usleep_range(1000, 1500); } - i915_audio_component_put_power(kdev, cookie); + intel_audio_component_put_power(kdev, cookie); } /* Get CDCLK in kHz */ -static int i915_audio_component_get_cdclk_freq(struct device *kdev) +static int intel_audio_component_get_cdclk_freq(struct device *kdev) { struct intel_display *display = to_intel_display(kdev); @@ -1169,8 +1169,8 @@ static struct intel_audio_state *find_audio_state(struct intel_display *display, return NULL; } -static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, - int cpu_transcoder, int rate) +static int intel_audio_component_sync_audio_rate(struct device *kdev, int port, + int cpu_transcoder, int rate) { struct intel_display *display = to_intel_display(kdev); struct i915_audio_component *acomp = display->audio.component; @@ -1183,7 +1183,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, if (!HAS_DDI(display)) return 0; - cookie = i915_audio_component_get_power(kdev); + cookie = intel_audio_component_get_power(kdev); mutex_lock(&display->audio.mutex); audio_state = find_audio_state(display, port, cpu_transcoder); @@ -1207,13 +1207,13 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, unlock: mutex_unlock(&display->audio.mutex); - i915_audio_component_put_power(kdev, cookie); + intel_audio_component_put_power(kdev, cookie); return err; } -static int i915_audio_component_get_eld(struct device *kdev, int port, - int cpu_transcoder, bool *enabled, - unsigned char *buf, int max_bytes) +static int intel_audio_component_get_eld(struct device *kdev, int port, + int cpu_transcoder, bool *enabled, + unsigned char *buf, int max_bytes) { struct intel_display *display = to_intel_display(kdev); const struct intel_audio_state *audio_state; @@ -1241,18 +1241,18 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, return ret; } -static const struct drm_audio_component_ops i915_audio_component_ops = { - .owner = THIS_MODULE, - .get_power = i915_audio_component_get_power, - .put_power = i915_audio_component_put_power, - .codec_wake_override = i915_audio_component_codec_wake_override, - .get_cdclk_freq = i915_audio_component_get_cdclk_freq, - .sync_audio_rate = i915_audio_component_sync_audio_rate, - .get_eld = i915_audio_component_get_eld, +static const struct drm_audio_component_ops intel_audio_component_ops = { + .owner = THIS_MODULE, + .get_power = intel_audio_component_get_power, + .put_power = intel_audio_component_put_power, + .codec_wake_override = intel_audio_component_codec_wake_override, + .get_cdclk_freq = intel_audio_component_get_cdclk_freq, + .sync_audio_rate = intel_audio_component_sync_audio_rate, + .get_eld = intel_audio_component_get_eld, }; -static int i915_audio_component_bind(struct device *drv_kdev, - struct device *hda_kdev, void *data) +static int intel_audio_component_bind(struct device *drv_kdev, + struct device *hda_kdev, void *data) { struct intel_display *display = to_intel_display(drv_kdev); struct i915_audio_component *acomp = data; @@ -1267,7 +1267,7 @@ static int i915_audio_component_bind(struct device *drv_kdev, return -ENOMEM; drm_modeset_lock_all(display->drm); - acomp->base.ops = &i915_audio_component_ops; + acomp->base.ops = &intel_audio_component_ops; acomp->base.dev = drv_kdev; BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) @@ -1278,8 +1278,8 @@ static int i915_audio_component_bind(struct device *drv_kdev, return 0; } -static void i915_audio_component_unbind(struct device *drv_kdev, - struct device *hda_kdev, void *data) +static void intel_audio_component_unbind(struct device *drv_kdev, + struct device *hda_kdev, void *data) { struct intel_display *display = to_intel_display(drv_kdev); struct i915_audio_component *acomp = data; @@ -1298,9 +1298,9 @@ static void i915_audio_component_unbind(struct device *drv_kdev, display->audio.power_refcount); } -static const struct component_ops i915_audio_component_bind_ops = { - .bind = i915_audio_component_bind, - .unbind = i915_audio_component_unbind, +static const struct component_ops intel_audio_component_bind_ops = { + .bind = intel_audio_component_bind, + .unbind = intel_audio_component_unbind, }; #define AUD_FREQ_TMODE_SHIFT 14 @@ -1313,7 +1313,7 @@ static const struct component_ops i915_audio_component_bind_ops = { #define AUD_FREQ_TGL_BROKEN (AUD_FREQ_8T | AUD_FREQ_PULLCLKS(2) | AUD_FREQ_BCLK_96M) /** - * i915_audio_component_init - initialize and register the audio component + * intel_audio_component_init - initialize and register the audio component * @display: display device * * This will register with the component framework a child component which @@ -1328,7 +1328,7 @@ static const struct component_ops i915_audio_component_bind_ops = { * We ignore any error during registration and continue with reduced * functionality (i.e. without HDMI audio). */ -static void i915_audio_component_init(struct intel_display *display) +static void intel_audio_component_init(struct intel_display *display) { u32 aud_freq, aud_freq_init; @@ -1356,12 +1356,12 @@ static void i915_audio_component_init(struct intel_display *display) intel_audio_cdclk_change_post(display); } -static void i915_audio_component_register(struct intel_display *display) +static void intel_audio_component_register(struct intel_display *display) { int ret; ret = component_add_typed(display->drm->dev, - &i915_audio_component_bind_ops, + &intel_audio_component_bind_ops, I915_COMPONENT_AUDIO); if (ret < 0) { drm_err(display->drm, @@ -1374,18 +1374,18 @@ static void i915_audio_component_register(struct intel_display *display) } /** - * i915_audio_component_cleanup - deregister the audio component + * intel_audio_component_cleanup - deregister the audio component * @display: display device * * Deregisters the audio component, breaking any existing binding to the * corresponding snd_hda_intel driver's master component. */ -static void i915_audio_component_cleanup(struct intel_display *display) +static void intel_audio_component_cleanup(struct intel_display *display) { if (!display->audio.component_registered) return; - component_del(display->drm->dev, &i915_audio_component_bind_ops); + component_del(display->drm->dev, &intel_audio_component_bind_ops); display->audio.component_registered = false; } @@ -1398,13 +1398,13 @@ static void i915_audio_component_cleanup(struct intel_display *display) void intel_audio_init(struct intel_display *display) { if (intel_lpe_audio_init(display) < 0) - i915_audio_component_init(display); + intel_audio_component_init(display); } void intel_audio_register(struct intel_display *display) { if (!display->audio.lpe.platdev) - i915_audio_component_register(display); + intel_audio_component_register(display); } /** @@ -1416,5 +1416,5 @@ void intel_audio_deinit(struct intel_display *display) if (display->audio.lpe.platdev) intel_lpe_audio_teardown(display); else - i915_audio_component_cleanup(display); + intel_audio_component_cleanup(display); } -- cgit v1.2.3-59-g8ed1b From dc4afc0de9654f88676d77094a38f9451d519011 Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Mon, 13 Jan 2025 12:47:41 -0300 Subject: drm/v3d: Remove `v3d->cpu_job` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPU jobs, like Cache Clean jobs, execute synchronously once the DRM scheduler starts running them. Consequently, a global `v3d->cpu_job` variable is unnecessary, as everything is managed within the `v3d_cpu_job_run()` function. This commit removes the `v3d->cpu_job` pointer, as it is not needed. Signed-off-by: Maíra Canal Reviewed-by: Jose Maria Casanova Crespo Link: https://patchwork.freedesktop.org/patch/msgid/20250113154741.67520-2-mcanal@igalia.com --- drivers/gpu/drm/v3d/v3d_drv.h | 1 - drivers/gpu/drm/v3d/v3d_sched.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index dc1cfe2e14be..9deaefa0f95b 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -147,7 +147,6 @@ struct v3d_dev { struct v3d_render_job *render_job; struct v3d_tfu_job *tfu_job; struct v3d_csd_job *csd_job; - struct v3d_cpu_job *cpu_job; struct v3d_queue_state queue[V3D_MAX_QUEUES]; diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index da08ddb01d21..961465128d80 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -656,8 +656,6 @@ v3d_cpu_job_run(struct drm_sched_job *sched_job) struct v3d_cpu_job *job = to_cpu_job(sched_job); struct v3d_dev *v3d = job->base.v3d; - v3d->cpu_job = job; - if (job->job_type >= ARRAY_SIZE(cpu_job_function)) { DRM_DEBUG_DRIVER("Unknown CPU job: %d\n", job->job_type); return NULL; -- cgit v1.2.3-59-g8ed1b From 3318ef9888d5b4f5c5a9473180fd0b16e9ef266d Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 6 Jan 2025 15:43:13 -0800 Subject: drm/xe: Remove unused "mmio_ext" code The "mmio_ext" and 'REG_EXT" code is currently unused on any existing platform. Going forward, this also isn't the design we want to use for any future platforms/features either, so we should just go ahead and remove the dead code to avoid confusion. mmio_ext was originally added in an attempt to hack around the early (mis)design of the Xe driver, which used xe_gt as the target for all register MMIO access, even those completely unrelated to the GT subunit of the hardware. With the introduction of commit 34953ee349dd ("drm/xe: Create dedicated xe_mmio structure") and its follow-up patches, that misdesign has been corrected and access to register MMIO regions specific to hardware units is now done through xe_mmio structures which encapsulate an iomap, region size, and some other metadata. Although all of the registers used by the driver today happen to fall within one specific PCI BAR region, and thus re-use a single device-wide iomap, there's no requirement that this stay true for future platforms or features. I.e., if a future platform adds a new 'foo' hardware unit that exists at a different area in the BAR, or even in a completely different BAR, then that would be handled by doing a separate iomap of that unit's register region and wrapping it in its own 'struct xe_mmio foo_regs' structure. The pointer to the new 'foo_regs' could be placed within the xe_device, xe_tile, xe_gt, etc., according to where the new hardware unit falls within the current hardware hierarchy. This effectively reverts the following commits, although parts of these commits had already vanished or changed with the earlier xe_mmio refactor work: - commit 399a13323f0d ("drm/xe: add 28-bit address support in struct xe_reg") - commit fdef72e02e20 ("drm/xe: add a flag to bypass multi-tile config from MTCFG reg") - commit 866b2b176434 ("drm/xe: add MMIO extension support flags") - commit ef29b390c734 ("drm/xe: map MMIO BAR according to the num of tiles in device desc") - commit a4e2f3a299ea ("drm/xe: refactor xe_mmio_probe_tiles to support MMIO extension") Cc: Lucas De Marchi Cc: Rodrigo Vivi Cc: Koby Elbaz Acked-by: Maciej Patelczyk Reviewed-by: Reviewed-by: Lucas De Marchi Reviewed-by: Stuart Summers Link: https://patchwork.freedesktop.org/patch/msgid/20250106234312.2986065-2-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_reg_defs.h | 16 +------------- drivers/gpu/drm/xe/xe_device_types.h | 11 ---------- drivers/gpu/drm/xe/xe_mmio.c | 39 ----------------------------------- drivers/gpu/drm/xe/xe_pci.c | 3 --- drivers/gpu/drm/xe/xe_pci_types.h | 2 -- 5 files changed, 1 insertion(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/regs/xe_reg_defs.h b/drivers/gpu/drm/xe/regs/xe_reg_defs.h index 0eedd6c26b1b..89716172fbb8 100644 --- a/drivers/gpu/drm/xe/regs/xe_reg_defs.h +++ b/drivers/gpu/drm/xe/regs/xe_reg_defs.h @@ -21,7 +21,7 @@ struct xe_reg { union { struct { /** @addr: address */ - u32 addr:28; + u32 addr:22; /** * @masked: register is "masked", with upper 16bits used * to identify the bits that are updated on the lower @@ -41,10 +41,6 @@ struct xe_reg { * @vf: register is accessible from the Virtual Function. */ u32 vf:1; - /** - * @ext: access MMIO extension space for current register. - */ - u32 ext:1; }; /** @raw: Raw value with both address and options */ u32 raw; @@ -111,16 +107,6 @@ struct xe_reg_mcr { */ #define XE_REG(r_, ...) ((const struct xe_reg)XE_REG_INITIALIZER(r_, ##__VA_ARGS__)) -/** - * XE_REG_EXT - Create a struct xe_reg from extension offset and additional - * flags - * @r_: Register extension offset - * @...: Additional options like access mode. See struct xe_reg for available - * options. - */ -#define XE_REG_EXT(r_, ...) \ - ((const struct xe_reg)XE_REG_INITIALIZER(r_, ##__VA_ARGS__, .ext = 1)) - /** * XE_REG_MCR - Create a struct xe_reg_mcr from offset and additional flags * @r_: Register offset diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 8a7b15972413..16ebb2859877 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -186,13 +186,6 @@ struct xe_tile { */ struct xe_mmio mmio; - /** - * @mmio_ext: MMIO-extension info for a tile. - * - * Each tile has its own additional 256MB (28-bit) MMIO-extension space. - */ - struct xe_mmio mmio_ext; - /** @mem: memory management info for tile */ struct { /** @@ -263,8 +256,6 @@ struct xe_device { const char *graphics_name; /** @info.media_name: media IP name */ const char *media_name; - /** @info.tile_mmio_ext_size: size of MMIO extension space, per-tile */ - u32 tile_mmio_ext_size; /** @info.graphics_verx100: graphics IP version */ u32 graphics_verx100; /** @info.media_verx100: media IP version */ @@ -314,8 +305,6 @@ struct xe_device { u8 has_heci_gscfi:1; /** @info.has_llc: Device has a shared CPU+GPU last level cache */ u8 has_llc:1; - /** @info.has_mmio_ext: Device has extra MMIO address range */ - u8 has_mmio_ext:1; /** @info.has_range_tlb_invalidation: Has range based TLB invalidations */ u8 has_range_tlb_invalidation:1; /** @info.has_sriov: Supports SR-IOV */ diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index a48f239cad1c..d321a21aacf0 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -103,50 +103,11 @@ static void mmio_multi_tile_setup(struct xe_device *xe, size_t tile_mmio_size) } } -/* - * On top of all the multi-tile MMIO space there can be a platform-dependent - * extension for each tile, resulting in a layout like below: - * - * .----------------------. <- ext_base + tile_count * tile_mmio_ext_size - * | .... | - * |----------------------| <- ext_base + 2 * tile_mmio_ext_size - * | tile1->mmio_ext.regs | - * |----------------------| <- ext_base + 1 * tile_mmio_ext_size - * | tile0->mmio_ext.regs | - * |======================| <- ext_base = tile_count * tile_mmio_size - * | | - * | mmio.regs | - * | | - * '----------------------' <- 0MB - * - * Set up the tile[]->mmio_ext pointers/sizes. - */ -static void mmio_extension_setup(struct xe_device *xe, size_t tile_mmio_size, - size_t tile_mmio_ext_size) -{ - struct xe_tile *tile; - void __iomem *regs; - u8 id; - - if (!xe->info.has_mmio_ext) - return; - - regs = xe->mmio.regs + tile_mmio_size * xe->info.tile_count; - for_each_tile(tile, xe, id) { - tile->mmio_ext.regs_size = tile_mmio_ext_size; - tile->mmio_ext.regs = regs; - tile->mmio_ext.tile = tile; - regs += tile_mmio_ext_size; - } -} - int xe_mmio_probe_tiles(struct xe_device *xe) { size_t tile_mmio_size = SZ_16M; - size_t tile_mmio_ext_size = xe->info.tile_mmio_ext_size; mmio_multi_tile_setup(xe, tile_mmio_size); - mmio_extension_setup(xe, tile_mmio_size, tile_mmio_ext_size); return devm_add_action_or_reset(xe->drm.dev, tiles_fini, xe); } diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 39be74848e44..48d1c81d441e 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -61,7 +61,6 @@ struct xe_device_desc { u8 has_heci_gscfi:1; u8 has_heci_cscfi:1; u8 has_llc:1; - u8 has_mmio_ext:1; u8 has_sriov:1; u8 skip_guc_pc:1; u8 skip_mtcfg:1; @@ -617,7 +616,6 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.has_heci_gscfi = desc->has_heci_gscfi; xe->info.has_heci_cscfi = desc->has_heci_cscfi; xe->info.has_llc = desc->has_llc; - xe->info.has_mmio_ext = desc->has_mmio_ext; xe->info.has_sriov = desc->has_sriov; xe->info.skip_guc_pc = desc->skip_guc_pc; xe->info.skip_mtcfg = desc->skip_mtcfg; @@ -677,7 +675,6 @@ static int xe_info_init(struct xe_device *xe, xe->info.graphics_name = graphics_desc->name; xe->info.media_name = media_desc ? media_desc->name : "none"; - xe->info.tile_mmio_ext_size = graphics_desc->tile_mmio_ext_size; xe->info.dma_mask_size = graphics_desc->dma_mask_size; xe->info.vram_flags = graphics_desc->vram_flags; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 79b0f80376a4..873efec5cdee 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -20,8 +20,6 @@ struct xe_graphics_desc { u64 hw_engine_mask; /* hardware engines provided by graphics IP */ - u32 tile_mmio_ext_size; /* size of MMIO extension space, per-tile */ - u8 max_remote_tiles:2; u8 has_asid:1; -- cgit v1.2.3-59-g8ed1b From 0af944f0e3082ff517958b1cea76fb9b8cb379dd Mon Sep 17 00:00:00 2001 From: Oak Zeng Date: Fri, 10 Jan 2025 16:01:37 -0500 Subject: drm/xe: Reject BO eviction if BO is bound to current VM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a follow up fix for https://patchwork.freedesktop.org/patch/msgid/20241203021929.1919730-1-oak.zeng@intel.com The overall goal is to fail vm_bind when there is memory pressure. See more details in the commit message of above patch. Abbove patch fixes the issue when user pass in a vm_id parameter during gem_create. If user doesn't pass in a vm_id during gem_create, above patch doesn't help. This patch further reject BO eviction (which could be triggered by bo validation) if BO is bound to the current VM. vm_bind could fail due to the eviction failure. The BO to VM reverse mapping structure is used to determine whether BO is bound to VM. v2: Move vm_bo definition from function scope to if(evict) clause (Thomas) Further constraint the condition by adding ctx->resv (Thomas) Add a short comment describe the change. Suggested-by: Thomas Hellström Signed-off-by: Oak Zeng Reviewed-by: Thomas Hellström Signed-off-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20250110210137.3181576-1-oak.zeng@intel.com --- drivers/gpu/drm/xe/xe_bo.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 3f5391d416d4..4f077c11e8e2 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -713,6 +713,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, goto out; } + /* Reject BO eviction if BO is bound to current VM. */ + if (evict && ctx->resv) { + struct drm_gpuvm_bo *vm_bo; + + drm_gem_for_each_gpuvm_bo(vm_bo, &bo->ttm.base) { + struct xe_vm *vm = gpuvm_to_vm(vm_bo->vm); + + if (xe_vm_resv(vm) == ctx->resv && + xe_vm_in_preempt_fence_mode(vm)) { + ret = -EBUSY; + goto out; + } + } + } + /* * Failed multi-hop where the old_mem is still marked as * TTM_PL_FLAG_TEMPORARY, should just be a dummy move. -- cgit v1.2.3-59-g8ed1b From 00728273bdf1001f8d2f7b65bc398000d7defe0b Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 15 Jan 2025 12:49:42 +0000 Subject: drm/tests/buddy: fix build with unused prng MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We no longer use the prng, which leads to the following warning: drivers/gpu/drm/tests/drm_buddy_test.c: In function ‘drm_test_buddy_alloc_clear’: drivers/gpu/drm/tests/drm_buddy_test.c:264:23: error: unused variable ‘prng’ [-Werror=unused-variable] 264 | DRM_RND_STATE(prng, random_seed); v2 (Thomas) - Add Closes links Reported-by: Jani Nikula Closes: https://lore.kernel.org/dri-devel/875xmggvcs.fsf@intel.com/ Reported-by: Thomas Hellström Closes: https://lore.kernel.org/dri-devel/3f816555e6913fdbcb254523f65c98088d70581b.camel@intel.com/ Fixes: 8cb3a1e2b350 ("drm/buddy: Add a testcase to verify the multiroot fini") Signed-off-by: Matthew Auld Cc: Arunpravin Paneer Selvam Cc: Christian König Reviewed-by: Thomas Hellström Reviewed-by: Arunpravin Paneer Selvam Signed-off-by: Arunpravin Paneer Selvam Link: https://patchwork.freedesktop.org/patch/msgid/20250115124941.155990-2-matthew.auld@intel.com --- drivers/gpu/drm/tests/drm_buddy_test.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c index 4b5818f9f2a9..7a0e523651f0 100644 --- a/drivers/gpu/drm/tests/drm_buddy_test.c +++ b/drivers/gpu/drm/tests/drm_buddy_test.c @@ -261,7 +261,6 @@ static void drm_test_buddy_alloc_range_bias(struct kunit *test) static void drm_test_buddy_alloc_clear(struct kunit *test) { unsigned long n_pages, total, i = 0; - DRM_RND_STATE(prng, random_seed); const unsigned long ps = SZ_4K; struct drm_buddy_block *block; const int max_order = 12; -- cgit v1.2.3-59-g8ed1b From 778c29fca7557baa514dd0cf6efaa654845edf60 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:50 +0200 Subject: drm/i915: Extract intel_crtc_vblank_delay() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the vblank delay computation into a separate function. We'll need more logic here soon and we don't want to pollute intel_crtc_compute_config() with low level details. We'll use HAS_DSB() to determine if any delay might be required or not because delayed vblank only really exists for the purposes of the DSB. It also doesn't event exists on any pre-tgl platforms, which also don't have DSB. I was midly tempted to check for the enable_dsb modparam here actually, but as that can be changed dynamically via debugfs we'd need to either reconfigure it on the fly or force a modeset. Neither will happen currently, so we'll just assume DSB may be used of the platform supports it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-2-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4271da219b41..5530bcf32b87 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2610,16 +2610,29 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) return 0; } -static bool intel_crtc_needs_wa_14015401596(struct intel_crtc_state *crtc_state) +static bool intel_crtc_needs_wa_14015401596(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; return intel_vrr_possible(crtc_state) && crtc_state->has_psr && - adjusted_mode->crtc_vblank_start == adjusted_mode->crtc_vdisplay && IS_DISPLAY_VER(display, 13, 14); } +static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + int vblank_delay = 0; + + if (!HAS_DSB(display)) + return 0; + + /* Wa_14015401596 */ + if (intel_crtc_needs_wa_14015401596(crtc_state)) + vblank_delay = max(vblank_delay, 1); + + return vblank_delay; +} + static int intel_crtc_compute_config(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -2629,9 +2642,8 @@ static int intel_crtc_compute_config(struct intel_atomic_state *state, &crtc_state->hw.adjusted_mode; int ret; - /* Wa_14015401596 */ - if (intel_crtc_needs_wa_14015401596(crtc_state)) - adjusted_mode->crtc_vblank_start += 1; + adjusted_mode->crtc_vblank_start += + intel_crtc_vblank_delay(crtc_state); ret = intel_dpll_crtc_compute_clock(state, crtc); if (ret) -- cgit v1.2.3-59-g8ed1b From 4745ef7a173f4c9182099870c627de309c07b204 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:51 +0200 Subject: drm/i915: Check vblank delay validity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we have enough vblank for the computed vblank delay. Supposedly we'd reject things anyway later if this gets violated, but it seems nicer to do some basic sanity checks early just so we can be sure the basic relationship vblank_end > vblank_start always holds. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-3-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 31 ++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5530bcf32b87..f5d2eacce119 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2633,17 +2633,40 @@ static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state) return vblank_delay; } -static int intel_crtc_compute_config(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int intel_crtc_compute_vblank_delay(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int vblank_delay, max_vblank_delay; + + vblank_delay = intel_crtc_vblank_delay(crtc_state); + max_vblank_delay = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start - 1; + + if (vblank_delay > max_vblank_delay) { + drm_dbg_kms(display->drm, "[CRTC:%d:%s] vblank delay (%d) exceeds max (%d)\n", + crtc->base.base.id, crtc->base.name, vblank_delay, max_vblank_delay); + return -EINVAL; + } + + adjusted_mode->crtc_vblank_start += vblank_delay; + + return 0; +} + +static int intel_crtc_compute_config(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; - adjusted_mode->crtc_vblank_start += - intel_crtc_vblank_delay(crtc_state); + ret = intel_crtc_compute_vblank_delay(state, crtc); + if (ret) + return ret; ret = intel_dpll_crtc_compute_clock(state, crtc); if (ret) -- cgit v1.2.3-59-g8ed1b From 51e7f44027a184f5f9048caa0d7e29eebdd9a5cc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:52 +0200 Subject: drm/i915: Fix include order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the headers in the correct alphabetical order. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-4-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vrr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 70088e355055..66f9ce2b4486 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -7,9 +7,9 @@ #include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_dp.h" #include "intel_vrr.h" #include "intel_vrr_regs.h" -#include "intel_dp.h" #define FIXED_POINT_PRECISION 100 #define CMRR_PRECISION_TOLERANCE 10 -- cgit v1.2.3-59-g8ed1b From b7eeed399b2851b140119e4866cabaaf1cba182d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:53 +0200 Subject: drm/i915: Introduce intel_vrr_{vmin,vmax}_vtotal() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ICL/TGL vmin/vmax/flipline won't actually match the vtotal values (currently they do, but that is wrong and needs to be fixed). Add a few helpers that will compute the actual vtotal values for us. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-5-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dsb.c | 2 +- drivers/gpu/drm/i915/display/intel_vblank.c | 4 ++-- drivers/gpu/drm/i915/display/intel_vrr.c | 11 +++++++++++ drivers/gpu/drm/i915/display/intel_vrr.h | 2 ++ 4 files changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index e6f8fc743fb4..fcb8bf9cb313 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -140,7 +140,7 @@ static int dsb_vtotal(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); if (pre_commit_is_vrr_active(state, crtc)) - return crtc_state->vrr.vmax; + return intel_vrr_vmax_vtotal(crtc_state); else return intel_mode_vtotal(&crtc_state->hw.adjusted_mode); } diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index a95fb3349eba..6f0e0c64187d 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -523,8 +523,8 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, drm_WARN_ON(display->drm, (mode_flags & I915_MODE_FLAG_VRR) == 0); - adjusted_mode.crtc_vtotal = crtc_state->vrr.vmax; - adjusted_mode.crtc_vblank_end = crtc_state->vrr.vmax; + adjusted_mode.crtc_vtotal = intel_vrr_vmax_vtotal(crtc_state); + adjusted_mode.crtc_vblank_end = intel_vrr_vmax_vtotal(crtc_state); adjusted_mode.crtc_vblank_start = intel_vrr_vmin_vblank_start(crtc_state); vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state); } else { diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 66f9ce2b4486..2e9c286bb079 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -102,6 +102,17 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1; } +int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state) +{ + /* Min vblank actually determined by flipline that is always >=vmin+1 */ + return crtc_state->vrr.vmin + 1; +} + +int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->vrr.vmax; +} + int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state) { /* Min vblank actually determined by flipline that is always >=vmin+1 */ diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h index b3b45c675020..75db88ae9cc4 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.h +++ b/drivers/gpu/drm/i915/display/intel_vrr.h @@ -26,6 +26,8 @@ void intel_vrr_send_push(const struct intel_crtc_state *crtc_state); bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state); void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state); void intel_vrr_get_config(struct intel_crtc_state *crtc_state); +int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state); +int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state); int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state); int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state); -- cgit v1.2.3-59-g8ed1b From c14f66c6e46728db2cf314725e68655ac2f499dc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:54 +0200 Subject: drm/i915: Move framestart/etc. state dump to a better spot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Try to dump all the important stuff relating to the display timings in one spot. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-6-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 1faef60be472..9d930ff862cf 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -250,9 +250,6 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); } - drm_printf(&p, "framestart delay: %d, MSA timing delay: %d\n", - pipe_config->framestart_delay, pipe_config->msa_timing_delay); - drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", pipe_config->has_audio, pipe_config->has_infoframe, pipe_config->infoframes.enable); @@ -286,6 +283,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, drm_print_hex_dump(&p, "ELD: ", pipe_config->eld, drm_eld_size(pipe_config->eld)); + drm_printf(&p, "framestart delay: %d, MSA timing delay: %d\n", + pipe_config->framestart_delay, pipe_config->msa_timing_delay); + drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", str_yes_no(pipe_config->vrr.enable), pipe_config->vrr.vmin, pipe_config->vrr.vmax, -- cgit v1.2.3-59-g8ed1b From af14b81e9f04b35d578627f6305d87010d0ef0ad Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:55 +0200 Subject: drm/i915: Include the vblank delay in the state dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While one can look at the crtc timings to determine the actual vblank dealy, it seems nicer to provide a more human readable dump of it to ease our lives. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-7-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 9d930ff862cf..27ce34df8482 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -283,7 +283,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, drm_print_hex_dump(&p, "ELD: ", pipe_config->eld, drm_eld_size(pipe_config->eld)); - drm_printf(&p, "framestart delay: %d, MSA timing delay: %d\n", + drm_printf(&p, "vblank delay: %d, framestart delay: %d, MSA timing delay: %d\n", + pipe_config->hw.adjusted_mode.crtc_vblank_start - + pipe_config->hw.adjusted_mode.crtc_vdisplay, pipe_config->framestart_delay, pipe_config->msa_timing_delay); drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", -- cgit v1.2.3-59-g8ed1b From 97b6a2eef43f8dac2f36cfde2d813eb2b5edd26e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:56 +0200 Subject: drm/i915/vrr: Improve VRR state dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dump the calculated vmin/vmax vtotal values in addition to the raw vmin/vmax/flipline values. Makes it much easier to see what kind of scanline values we should be expecting from the hardware. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-8-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 27ce34df8482..97e3cdccda01 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -288,13 +288,14 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, pipe_config->hw.adjusted_mode.crtc_vdisplay, pipe_config->framestart_delay, pipe_config->msa_timing_delay); - drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", + drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, flipline: %d, pipeline full: %d, guardband: %d\n", str_yes_no(pipe_config->vrr.enable), - pipe_config->vrr.vmin, pipe_config->vrr.vmax, - pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband, - pipe_config->vrr.flipline, - intel_vrr_vmin_vblank_start(pipe_config), - intel_vrr_vmax_vblank_start(pipe_config)); + pipe_config->vrr.vmin, pipe_config->vrr.vmax, pipe_config->vrr.flipline, + pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband); + + drm_printf(&p, "vrr: vmin vblank: %d, vmax vblank: %d, vmin vtotal: %d, vmax vtotal: %d\n", + intel_vrr_vmin_vblank_start(pipe_config), intel_vrr_vmax_vblank_start(pipe_config), + intel_vrr_vmin_vtotal(pipe_config), intel_vrr_vmax_vtotal(pipe_config)); drm_printf(&p, "requested mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&pipe_config->hw.mode)); -- cgit v1.2.3-59-g8ed1b From ab684293168c7c817fc6089f290496cd6bfeec0b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:57 +0200 Subject: drm/i915: Include the scanline offset in the state dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When looking at raw hardware scanline numbers it's helpful to remember what the offset between the hardware values and our more human readable numbers should be. Include that in the state dump. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-9-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 97e3cdccda01..1fbaa67e2fea 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -10,6 +10,7 @@ #include "intel_crtc_state_dump.h" #include "intel_display_types.h" #include "intel_hdmi.h" +#include "intel_vblank.h" #include "intel_vdsc.h" #include "intel_vrr.h" @@ -283,6 +284,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, drm_print_hex_dump(&p, "ELD: ", pipe_config->eld, drm_eld_size(pipe_config->eld)); + drm_printf(&p, "scanline offset: %d\n", + intel_crtc_scanline_offset(pipe_config)); + drm_printf(&p, "vblank delay: %d, framestart delay: %d, MSA timing delay: %d\n", pipe_config->hw.adjusted_mode.crtc_vblank_start - pipe_config->hw.adjusted_mode.crtc_vdisplay, -- cgit v1.2.3-59-g8ed1b From 730ac786e869b1a98323f354e1d005cfc4d99fe9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:58 +0200 Subject: drm/i915: Extract intel_mode_vblank_delay() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the code that computes the hardware centric view of the vblank delay into a helper. We'll need a slightly different variant for VRR soon. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-10-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dsb.c | 3 +-- drivers/gpu/drm/i915/display/intel_vblank.c | 8 ++++++-- drivers/gpu/drm/i915/display/intel_vblank.h | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index fcb8bf9cb313..d755825edb35 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -130,8 +130,7 @@ pre_commit_crtc_state(struct intel_atomic_state *state, static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state) { - return intel_mode_vblank_start(&crtc_state->hw.adjusted_mode) - - intel_mode_vdisplay(&crtc_state->hw.adjusted_mode); + return intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode); } static int dsb_vtotal(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 6f0e0c64187d..ee33a49d9873 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -597,6 +597,11 @@ int intel_mode_vtotal(const struct drm_display_mode *mode) return vtotal; } +int intel_mode_vblank_delay(const struct drm_display_mode *mode) +{ + return intel_mode_vblank_start(mode) - intel_mode_vdisplay(mode); +} + void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state, struct intel_vblank_evade_ctx *evade) @@ -653,8 +658,7 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, */ if (intel_color_uses_dsb(new_crtc_state) || new_crtc_state->update_m_n || new_crtc_state->update_lrr) - evade->min -= intel_mode_vblank_start(adjusted_mode) - - intel_mode_vdisplay(adjusted_mode); + evade->min -= intel_mode_vblank_delay(adjusted_mode); } /* must be called with vblank interrupt already enabled! */ diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h index 6d7336256982..12c8e1f829a4 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.h +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -24,6 +24,7 @@ int intel_mode_vdisplay(const struct drm_display_mode *mode); int intel_mode_vblank_start(const struct drm_display_mode *mode); int intel_mode_vblank_end(const struct drm_display_mode *mode); int intel_mode_vtotal(const struct drm_display_mode *mode); +int intel_mode_vblank_delay(const struct drm_display_mode *mode); void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state, -- cgit v1.2.3-59-g8ed1b From a18bd2f32c6960bc5446db3d6d4e4b31267c863c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:09:59 +0200 Subject: drm/i915: Consolidate intel_pre_commit_crtc_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have approximately two copies of pre_commit_crtc_state(), one in the DSB code, the other in the vblank evasion code. Combine them into one. The slight difference between the two is that vblank evasion doesn't have a full atomic state (when called from the legacy cursor code), so it gets the old and new crtc state passed in by hand. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-11-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dsb.c | 37 +++++++++------------------- drivers/gpu/drm/i915/display/intel_vblank.c | 38 +++++++++++++++++++++-------- drivers/gpu/drm/i915/display/intel_vblank.h | 5 ++++ 3 files changed, 45 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index d755825edb35..673f75703785 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -109,25 +109,6 @@ static bool pre_commit_is_vrr_active(struct intel_atomic_state *state, return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, crtc); } -static const struct intel_crtc_state * -pre_commit_crtc_state(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); - const struct intel_crtc_state *new_crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - - /* - * During fastsets/etc. the transcoder is still - * running with the old timings at this point. - */ - if (intel_crtc_needs_modeset(new_crtc_state)) - return new_crtc_state; - else - return old_crtc_state; -} - static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state) { return intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode); @@ -136,7 +117,8 @@ static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state) static int dsb_vtotal(struct intel_atomic_state *state, struct intel_crtc *crtc) { - const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + const struct intel_crtc_state *crtc_state = + intel_pre_commit_crtc_state(state, crtc); if (pre_commit_is_vrr_active(state, crtc)) return intel_vrr_vmax_vtotal(crtc_state); @@ -147,7 +129,8 @@ static int dsb_vtotal(struct intel_atomic_state *state, static int dsb_dewake_scanline_start(struct intel_atomic_state *state, struct intel_crtc *crtc) { - const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + const struct intel_crtc_state *crtc_state = + intel_pre_commit_crtc_state(state, crtc); struct drm_i915_private *i915 = to_i915(state->base.dev); unsigned int latency = skl_watermark_max_latency(i915, 0); @@ -158,7 +141,8 @@ static int dsb_dewake_scanline_start(struct intel_atomic_state *state, static int dsb_dewake_scanline_end(struct intel_atomic_state *state, struct intel_crtc *crtc) { - const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + const struct intel_crtc_state *crtc_state = + intel_pre_commit_crtc_state(state, crtc); return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode); } @@ -166,7 +150,8 @@ static int dsb_dewake_scanline_end(struct intel_atomic_state *state, static int dsb_scanline_to_hw(struct intel_atomic_state *state, struct intel_crtc *crtc, int scanline) { - const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + const struct intel_crtc_state *crtc_state = + intel_pre_commit_crtc_state(state, crtc); int vtotal = dsb_vtotal(state, crtc); return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % vtotal; @@ -531,7 +516,8 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state, struct intel_dsb *dsb) { struct intel_crtc *crtc = dsb->crtc; - const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + const struct intel_crtc_state *crtc_state = + intel_pre_commit_crtc_state(state, crtc); /* FIXME calibrate sensibly */ int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 20); int vblank_delay = dsb_vblank_delay(crtc_state); @@ -623,7 +609,8 @@ void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state, struct intel_dsb *dsb) { struct intel_crtc *crtc = dsb->crtc; - const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc); + const struct intel_crtc_state *crtc_state = + intel_pre_commit_crtc_state(state, crtc); int usecs = intel_scanlines_to_usecs(&crtc_state->hw.adjusted_mode, dsb_vblank_delay(crtc_state)) + 1; diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index ee33a49d9873..3cf3cff0687a 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -602,6 +602,32 @@ int intel_mode_vblank_delay(const struct drm_display_mode *mode) return intel_mode_vblank_start(mode) - intel_mode_vdisplay(mode); } +static const struct intel_crtc_state * +pre_commit_crtc_state(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + /* + * During fastsets/etc. the transcoder is still + * running with the old timings at this point. + */ + if (intel_crtc_needs_modeset(new_crtc_state)) + return new_crtc_state; + else + return old_crtc_state; +} + +const struct intel_crtc_state * +intel_pre_commit_crtc_state(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + + return pre_commit_crtc_state(old_crtc_state, new_crtc_state); +} + void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state, struct intel_vblank_evade_ctx *evade) @@ -617,16 +643,8 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, display->platform.cherryview) && intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI); - /* - * During fastsets/etc. the transcoder is still - * running with the old timings at this point. - * - * TODO: maybe just use the active timings here? - */ - if (intel_crtc_needs_modeset(new_crtc_state)) - crtc_state = new_crtc_state; - else - crtc_state = old_crtc_state; + /* TODO: maybe just use the active timings here? */ + crtc_state = pre_commit_crtc_state(old_crtc_state, new_crtc_state); adjusted_mode = &crtc_state->hw.adjusted_mode; diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h index 12c8e1f829a4..21fbb08d61d5 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.h +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -11,6 +11,7 @@ struct drm_crtc; struct drm_display_mode; +struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; @@ -43,4 +44,8 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, bool vrr_enable); int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state); +const struct intel_crtc_state * +intel_pre_commit_crtc_state(struct intel_atomic_state *state, + struct intel_crtc *crtc); + #endif /* __INTEL_VBLANK_H__ */ -- cgit v1.2.3-59-g8ed1b From 047d9b28a56a95044f47b54ddad71e69809ecdb3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:10:00 +0200 Subject: drm/i915: Extract intel_crtc_active_timings() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declutter intel_crtc_update_active_timings() a bit by moving the code that determines the timings into a separate function. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-12-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vblank.c | 33 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 3cf3cff0687a..2a99bde457db 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -507,6 +507,23 @@ void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) wait_for_pipe_scanline_moving(crtc, true); } +static void intel_crtc_active_timings(struct drm_display_mode *mode, + int *vmax_vblank_start, + const struct intel_crtc_state *crtc_state, + bool vrr_enable) +{ + drm_mode_init(mode, &crtc_state->hw.adjusted_mode); + *vmax_vblank_start = 0; + + if (!vrr_enable) + return; + + mode->crtc_vtotal = intel_vrr_vmax_vtotal(crtc_state); + mode->crtc_vblank_end = intel_vrr_vmax_vtotal(crtc_state); + mode->crtc_vblank_start = intel_vrr_vmin_vblank_start(crtc_state); + *vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state); +} + void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, bool vrr_enable) { @@ -517,19 +534,13 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, int vmax_vblank_start = 0; unsigned long irqflags; - drm_mode_init(&adjusted_mode, &crtc_state->hw.adjusted_mode); - - if (vrr_enable) { - drm_WARN_ON(display->drm, - (mode_flags & I915_MODE_FLAG_VRR) == 0); + intel_crtc_active_timings(&adjusted_mode, &vmax_vblank_start, + crtc_state, vrr_enable); - adjusted_mode.crtc_vtotal = intel_vrr_vmax_vtotal(crtc_state); - adjusted_mode.crtc_vblank_end = intel_vrr_vmax_vtotal(crtc_state); - adjusted_mode.crtc_vblank_start = intel_vrr_vmin_vblank_start(crtc_state); - vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state); - } else { + if (vrr_enable) + drm_WARN_ON(display->drm, (mode_flags & I915_MODE_FLAG_VRR) == 0); + else mode_flags &= ~I915_MODE_FLAG_VRR; - } /* * Belts and suspenders locking to guarantee everyone sees 100% -- cgit v1.2.3-59-g8ed1b From 67badd015cba8d25fc88bf13cc49d8f7c377d547 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:10:01 +0200 Subject: drm/i915/vrr: Introduce intel_vrr_vblank_delay() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a VRR specific function for determining the current vblank delay. Currently thus will give the same answer as intel_mode_vblank_delay() but that will change later. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-13-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dsb.c | 18 ++++++++++++++---- drivers/gpu/drm/i915/display/intel_vblank.c | 7 ++++++- drivers/gpu/drm/i915/display/intel_vrr.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_vrr.h | 1 + 4 files changed, 27 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 673f75703785..89d3496bcbdb 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -109,9 +109,16 @@ static bool pre_commit_is_vrr_active(struct intel_atomic_state *state, return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, crtc); } -static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state) +static int dsb_vblank_delay(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - return intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode); + const struct intel_crtc_state *crtc_state = + intel_pre_commit_crtc_state(state, crtc); + + if (pre_commit_is_vrr_active(state, crtc)) + return intel_vrr_vblank_delay(crtc_state); + else + return intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode); } static int dsb_vtotal(struct intel_atomic_state *state, @@ -520,10 +527,11 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state, intel_pre_commit_crtc_state(state, crtc); /* FIXME calibrate sensibly */ int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 20); - int vblank_delay = dsb_vblank_delay(crtc_state); int start, end; if (pre_commit_is_vrr_active(state, crtc)) { + int vblank_delay = intel_vrr_vblank_delay(crtc_state); + end = intel_vrr_vmin_vblank_start(crtc_state); start = end - vblank_delay - latency; intel_dsb_wait_scanline_out(state, dsb, start, end); @@ -532,6 +540,8 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state, start = end - vblank_delay - latency; intel_dsb_wait_scanline_out(state, dsb, start, end); } else { + int vblank_delay = intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode); + end = intel_mode_vblank_start(&crtc_state->hw.adjusted_mode); start = end - vblank_delay - latency; intel_dsb_wait_scanline_out(state, dsb, start, end); @@ -612,7 +622,7 @@ void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state = intel_pre_commit_crtc_state(state, crtc); int usecs = intel_scanlines_to_usecs(&crtc_state->hw.adjusted_mode, - dsb_vblank_delay(crtc_state)) + 1; + dsb_vblank_delay(state, crtc)) + 1; intel_dsb_wait_usec(dsb, usecs); } diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 2a99bde457db..fb80e0bef08a 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -647,6 +647,7 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); const struct intel_crtc_state *crtc_state; const struct drm_display_mode *adjusted_mode; + int vblank_delay; evade->crtc = crtc; @@ -668,8 +669,12 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, evade->vblank_start = intel_vrr_vmin_vblank_start(crtc_state); else evade->vblank_start = intel_vrr_vmax_vblank_start(crtc_state); + + vblank_delay = intel_vrr_vblank_delay(crtc_state); } else { evade->vblank_start = intel_mode_vblank_start(adjusted_mode); + + vblank_delay = intel_mode_vblank_delay(adjusted_mode); } /* FIXME needs to be calibrated sensibly */ @@ -687,7 +692,7 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, */ if (intel_color_uses_dsb(new_crtc_state) || new_crtc_state->update_m_n || new_crtc_state->update_lrr) - evade->min -= intel_mode_vblank_delay(adjusted_mode); + evade->min -= vblank_delay; } /* must be called with vblank interrupt already enabled! */ diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 2e9c286bb079..05da10919ba8 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -75,6 +75,12 @@ intel_vrr_check_modeset(struct intel_atomic_state *state) } } +int intel_vrr_vblank_delay(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->hw.adjusted_mode.crtc_vblank_start - + crtc_state->hw.adjusted_mode.crtc_vdisplay; +} + /* * Without VRR registers get latched at: * vblank_start diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h index 75db88ae9cc4..8e8961adce39 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.h +++ b/drivers/gpu/drm/i915/display/intel_vrr.h @@ -30,5 +30,6 @@ int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state); int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state); int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state); int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state); +int intel_vrr_vblank_delay(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_VRR_H__ */ -- cgit v1.2.3-59-g8ed1b From 758736b0df3a55915014e54065d87e35cbfae7b8 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:10:02 +0200 Subject: drm/i915/vrr: Drop the extra vmin adjustment for ADL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently only ICL/TGL need the annoying vmin adjustment. On ADL+ we can program flipline==vmin and the hardware actually respects that properly. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-14-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vrr.c | 37 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 05da10919ba8..0f0c50265fc1 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -81,6 +81,19 @@ int intel_vrr_vblank_delay(const struct intel_crtc_state *crtc_state) crtc_state->hw.adjusted_mode.crtc_vdisplay; } +static int intel_vrr_flipline_offset(struct intel_display *display) +{ + /* ICL/TGL hardware imposes flipline>=vmin+1 */ + return DISPLAY_VER(display) < 13 ? 1 : 0; +} + +static int intel_vrr_vmin_flipline(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + return crtc_state->vrr.vmin + intel_vrr_flipline_offset(display); +} + /* * Without VRR registers get latched at: * vblank_start @@ -110,8 +123,8 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state) { - /* Min vblank actually determined by flipline that is always >=vmin+1 */ - return crtc_state->vrr.vmin + 1; + /* Min vblank actually determined by flipline */ + return intel_vrr_vmin_flipline(crtc_state); } int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state) @@ -121,8 +134,8 @@ int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state) int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state) { - /* Min vblank actually determined by flipline that is always >=vmin+1 */ - return crtc_state->vrr.vmin + 1 - intel_vrr_vblank_exit_length(crtc_state); + /* Min vblank actually determined by flipline */ + return intel_vrr_vmin_flipline(crtc_state) - intel_vrr_vblank_exit_length(crtc_state); } int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state) @@ -219,15 +232,17 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, if (vmin >= vmax) return; + crtc_state->vrr.vmin = vmin; + crtc_state->vrr.vmax = vmax; + + crtc_state->vrr.flipline = crtc_state->vrr.vmin; + /* * flipline determines the min vblank length the hardware will - * generate, and flipline>=vmin+1, hence we reduce vmin by one - * to make sure we can get the actual min vblank length. + * generate, and on ICL/TGL flipline>=vmin+1, hence we reduce + * vmin by one to make sure we can get the actual min vblank length. */ - crtc_state->vrr.vmin = vmin - 1; - crtc_state->vrr.vmax = vmax; - - crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1; + crtc_state->vrr.vmin -= intel_vrr_flipline_offset(display); /* * When panel is VRR capable and userspace has @@ -272,7 +287,7 @@ void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state) if (DISPLAY_VER(display) >= 13) { crtc_state->vrr.guardband = - crtc_state->vrr.vmin + 1 - adjusted_mode->crtc_vblank_start; + crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start; } else { crtc_state->vrr.pipeline_full = min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start - -- cgit v1.2.3-59-g8ed1b From b6e4f92a21e35ca8bd7b21b4b5866da59dd51c04 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:10:03 +0200 Subject: drm/i915/vrr: Fix vmin/vmax/flipline on TGL when using vblank delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out that TGL needs its vmin/vmax/flipline adjusted based on the vblank delay, otherwise the hardware pushes the vtotals further out. Make it so. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-15-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vrr.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 0f0c50265fc1..1110f0e65e88 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -117,30 +117,41 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat if (DISPLAY_VER(display) >= 13) return crtc_state->vrr.guardband; else - /* The hw imposes the extra scanline before frame start */ + /* hardware imposes one extra scanline somewhere */ return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1; } int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); + /* Min vblank actually determined by flipline */ - return intel_vrr_vmin_flipline(crtc_state); + if (DISPLAY_VER(display) >= 13) + return intel_vrr_vmin_flipline(crtc_state); + else + return intel_vrr_vmin_flipline(crtc_state) + + intel_vrr_vblank_delay(crtc_state); } int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state) { - return crtc_state->vrr.vmax; + struct intel_display *display = to_intel_display(crtc_state); + + if (DISPLAY_VER(display) >= 13) + return crtc_state->vrr.vmax; + else + return crtc_state->vrr.vmax + + intel_vrr_vblank_delay(crtc_state); } int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state) { - /* Min vblank actually determined by flipline */ - return intel_vrr_vmin_flipline(crtc_state) - intel_vrr_vblank_exit_length(crtc_state); + return intel_vrr_vmin_vtotal(crtc_state) - intel_vrr_vblank_exit_length(crtc_state); } int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state) { - return crtc_state->vrr.vmax - intel_vrr_vblank_exit_length(crtc_state); + return intel_vrr_vmax_vtotal(crtc_state) - intel_vrr_vblank_exit_length(crtc_state); } static bool @@ -289,9 +300,18 @@ void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state) crtc_state->vrr.guardband = crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start; } else { + /* hardware imposes one extra scanline somewhere */ crtc_state->vrr.pipeline_full = min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start - crtc_state->framestart_delay - 1); + + /* + * vmin/vmax/flipline also need to be adjusted by + * the vblank delay to maintain correct vtotals. + */ + crtc_state->vrr.vmin -= intel_vrr_vblank_delay(crtc_state); + crtc_state->vrr.vmax -= intel_vrr_vblank_delay(crtc_state); + crtc_state->vrr.flipline -= intel_vrr_vblank_delay(crtc_state); } } -- cgit v1.2.3-59-g8ed1b From 8b85eadabd0902bde4562c493f4e1068a0c80c2b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:10:04 +0200 Subject: drm/i915/vrr: Add extra vblank delay to estimates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ICL/TGL the VRR hardware injects an extra scanline just after vactive. This essentically behaves the same as an extra line of vblank delay, except it only appears in this one specific spot. Consider our DSB interrupt signalling scheme: 1. arm the update 2. wait for undelayed vblank (or rather safe window with VRR) 3. wait for enough usecs to get past the delayed vblank 4. signal interrupt to indicate that arming has latched If step 2 waits for end of vactive step 3 needs to account for the extra one scanline, or else we risk signalling the interrupt before the delayed vblank has actually elapsed. So include the extra scanline in our vblank delay estimates. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-16-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vrr.c | 33 ++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 1110f0e65e88..b5e30bfe1791 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -75,12 +75,33 @@ intel_vrr_check_modeset(struct intel_atomic_state *state) } } -int intel_vrr_vblank_delay(const struct intel_crtc_state *crtc_state) +static int intel_vrr_real_vblank_delay(const struct intel_crtc_state *crtc_state) { return crtc_state->hw.adjusted_mode.crtc_vblank_start - crtc_state->hw.adjusted_mode.crtc_vdisplay; } +static int intel_vrr_extra_vblank_delay(struct intel_display *display) +{ + /* + * On ICL/TGL VRR hardware inserts one extra scanline + * just after vactive, which pushes the vmin decision + * boundary ahead accordingly. We'll include the extra + * scanline in our vblank delay estimates to make sure + * that we never underestimate how long we have until + * the delayed vblank has passed. + */ + return DISPLAY_VER(display) < 13 ? 1 : 0; +} + +int intel_vrr_vblank_delay(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + return intel_vrr_real_vblank_delay(crtc_state) + + intel_vrr_extra_vblank_delay(display); +} + static int intel_vrr_flipline_offset(struct intel_display *display) { /* ICL/TGL hardware imposes flipline>=vmin+1 */ @@ -130,7 +151,7 @@ int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state) return intel_vrr_vmin_flipline(crtc_state); else return intel_vrr_vmin_flipline(crtc_state) + - intel_vrr_vblank_delay(crtc_state); + intel_vrr_real_vblank_delay(crtc_state); } int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state) @@ -141,7 +162,7 @@ int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state) return crtc_state->vrr.vmax; else return crtc_state->vrr.vmax + - intel_vrr_vblank_delay(crtc_state); + intel_vrr_real_vblank_delay(crtc_state); } int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state) @@ -309,9 +330,9 @@ void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state) * vmin/vmax/flipline also need to be adjusted by * the vblank delay to maintain correct vtotals. */ - crtc_state->vrr.vmin -= intel_vrr_vblank_delay(crtc_state); - crtc_state->vrr.vmax -= intel_vrr_vblank_delay(crtc_state); - crtc_state->vrr.flipline -= intel_vrr_vblank_delay(crtc_state); + crtc_state->vrr.vmin -= intel_vrr_real_vblank_delay(crtc_state); + crtc_state->vrr.vmax -= intel_vrr_real_vblank_delay(crtc_state); + crtc_state->vrr.flipline -= intel_vrr_real_vblank_delay(crtc_state); } } -- cgit v1.2.3-59-g8ed1b From fd95e73debdffd77febc0f0b4b304378856a5e6b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2024 23:10:05 +0200 Subject: drm/i915/vrr: Plumb the DSB into intel_vrr_send_push() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plumb the DSB down into intel_vrr_send_push() so that we can perform the opration on the DSB. TRANS_PUSH, being a transcoder register, needs non-posted writes to make it through. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-17-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_crtc.c | 2 +- drivers/gpu/drm/i915/display/intel_vrr.c | 14 +++++++++++--- drivers/gpu/drm/i915/display/intel_vrr.h | 4 +++- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index c910168602d2..3e8b52eaac27 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -714,7 +714,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state, * which would cause the next frame to terminate already at vmin * vblank start instead of vmax vblank start. */ - intel_vrr_send_push(new_crtc_state); + intel_vrr_send_push(NULL, new_crtc_state); local_irq_enable(); diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index b5e30bfe1791..b268a0a01cd1 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -390,7 +390,8 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state) crtc_state->vrr.flipline - 1); } -void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) +void intel_vrr_send_push(struct intel_dsb *dsb, + const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -398,8 +399,15 @@ void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) if (!crtc_state->vrr.enable) return; - intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), - TRANS_PUSH_EN | TRANS_PUSH_SEND); + if (dsb) + intel_dsb_nonpost_start(dsb); + + intel_de_write_dsb(display, dsb, + TRANS_PUSH(display, cpu_transcoder), + TRANS_PUSH_EN | TRANS_PUSH_SEND); + + if (dsb) + intel_dsb_nonpost_end(dsb); } bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h index 8e8961adce39..899cbf40f880 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.h +++ b/drivers/gpu/drm/i915/display/intel_vrr.h @@ -12,6 +12,7 @@ struct drm_connector_state; struct intel_atomic_state; struct intel_connector; struct intel_crtc_state; +struct intel_dsb; bool intel_vrr_is_capable(struct intel_connector *connector); bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh); @@ -22,7 +23,8 @@ void intel_vrr_compute_config(struct intel_crtc_state *crtc_state, void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state); void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state); void intel_vrr_enable(const struct intel_crtc_state *crtc_state); -void intel_vrr_send_push(const struct intel_crtc_state *crtc_state); +void intel_vrr_send_push(struct intel_dsb *dsb, + const struct intel_crtc_state *crtc_state); bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state); void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state); void intel_vrr_get_config(struct intel_crtc_state *crtc_state); -- cgit v1.2.3-59-g8ed1b From 1113fc0e826581bb56858b100cab46f1ceef69c7 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 20 Dec 2024 17:19:25 -0800 Subject: drm/i915: Add debug print about hw config table size Add debug info to help investigate a very rare bug: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13385 Signed-off-by: John Harrison Reviewed-by: Julia Filipchuk Link: https://patchwork.freedesktop.org/patch/msgid/20241221011925.3944625-1-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c index b67a15f74276..868195c33f5b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c @@ -7,6 +7,7 @@ #include "gt/intel_hwconfig.h" #include "i915_drv.h" #include "i915_memcpy.h" +#include "intel_guc_print.h" /* * GuC has a blob containing hardware configuration information (HWConfig). @@ -42,6 +43,8 @@ static int __guc_action_get_hwconfig(struct intel_guc *guc, }; int ret; + guc_dbg(guc, "Querying HW config table: size = %d, offset = 0x%08X\n", + ggtt_size, ggtt_offset); ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); if (ret == -ENXIO) return -ENOENT; -- cgit v1.2.3-59-g8ed1b From aaab5404b16f19b06c7d88787d7ba18d91eeb854 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 15 Jan 2025 09:50:52 -0500 Subject: drm/xe: Introduce GuC PC debugfs Allows the visualization of the current GuC power conservation status and policies. v2: Fix DCC msg (Vinay) v3: Simplify pc_get_state_string (Jonathan) Reviewed-by: Vinay Belgaumkar Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20250115145053.1142023-1-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc_debugfs.c | 15 ++++++++++ drivers/gpu/drm/xe/xe_guc_pc.c | 59 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_guc_pc.h | 2 ++ 3 files changed, 76 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_debugfs.c b/drivers/gpu/drm/xe/xe_guc_debugfs.c index 995b306aced7..0aff1d462bc0 100644 --- a/drivers/gpu/drm/xe/xe_guc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_guc_debugfs.c @@ -13,6 +13,7 @@ #include "xe_guc.h" #include "xe_guc_ct.h" #include "xe_guc_log.h" +#include "xe_guc_pc.h" #include "xe_macros.h" #include "xe_pm.h" @@ -60,10 +61,24 @@ static int guc_ctb(struct seq_file *m, void *data) return 0; } +static int guc_pc(struct seq_file *m, void *data) +{ + struct xe_guc *guc = node_to_guc(m->private); + struct xe_device *xe = guc_to_xe(guc); + struct drm_printer p = drm_seq_file_printer(m); + + xe_pm_runtime_get(xe); + xe_guc_pc_print(&guc->pc, &p); + xe_pm_runtime_put(xe); + + return 0; +} + static const struct drm_info_list debugfs_list[] = { {"guc_info", guc_info, 0}, {"guc_log", guc_log, 0}, {"guc_ctb", guc_ctb, 0}, + {"guc_pc", guc_pc, 0}, }; void xe_guc_debugfs_register(struct xe_guc *guc, struct dentry *parent) diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index df7f130fb663..43f9617baba2 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -8,6 +8,7 @@ #include #include +#include #include #include "abi/guc_actions_slpc_abi.h" @@ -1131,3 +1132,61 @@ int xe_guc_pc_init(struct xe_guc_pc *pc) return devm_add_action_or_reset(xe->drm.dev, xe_guc_pc_fini_hw, pc); } + +static const char *pc_get_state_string(struct xe_guc_pc *pc) +{ + switch (slpc_shared_data_read(pc, header.global_state)) { + case SLPC_GLOBAL_STATE_NOT_RUNNING: + return "not running"; + case SLPC_GLOBAL_STATE_INITIALIZING: + return "initializing"; + case SLPC_GLOBAL_STATE_RESETTING: + return "resetting"; + case SLPC_GLOBAL_STATE_RUNNING: + return "running"; + case SLPC_GLOBAL_STATE_SHUTTING_DOWN: + return "shutting down"; + case SLPC_GLOBAL_STATE_ERROR: + return "error"; + default: + return "unknown"; + } +} + +/** + * xe_guc_pc_print - Print GuC's Power Conservation information for debug + * @pc: Xe_GuC_PC instance + * @p: drm_printer + */ +void xe_guc_pc_print(struct xe_guc_pc *pc, struct drm_printer *p) +{ + drm_printf(p, "SLPC Shared Data Header:\n"); + drm_printf(p, "\tSize: %x\n", slpc_shared_data_read(pc, header.size)); + drm_printf(p, "\tGlobal State: %s\n", pc_get_state_string(pc)); + + if (pc_action_query_task_state(pc)) + return; + + drm_printf(p, "\nSLPC Tasks Status:\n"); + drm_printf(p, "\tGTPERF enabled: %s\n", + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & + SLPC_GTPERF_TASK_ENABLED)); + drm_printf(p, "\tDCC enabled: %s\n", + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & + SLPC_DCC_TASK_ENABLED)); + drm_printf(p, "\tDCC in use: %s\n", + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & + SLPC_IN_DCC)); + drm_printf(p, "\tBalancer enabled: %s\n", + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & + SLPC_BALANCER_ENABLED)); + drm_printf(p, "\tIBC enabled: %s\n", + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & + SLPC_IBC_TASK_ENABLED)); + drm_printf(p, "\tBalancer IA LMT enabled: %s\n", + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & + SLPC_BALANCER_IA_LMT_ENABLED)); + drm_printf(p, "\tBalancer IA LMT active: %s\n", + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & + SLPC_BALANCER_IA_LMT_ACTIVE)); +} diff --git a/drivers/gpu/drm/xe/xe_guc_pc.h b/drivers/gpu/drm/xe/xe_guc_pc.h index 619f59cd633c..39102b79602f 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.h +++ b/drivers/gpu/drm/xe/xe_guc_pc.h @@ -10,6 +10,7 @@ struct xe_guc_pc; enum slpc_gucrc_mode; +struct drm_printer; int xe_guc_pc_init(struct xe_guc_pc *pc); int xe_guc_pc_start(struct xe_guc_pc *pc); @@ -17,6 +18,7 @@ int xe_guc_pc_stop(struct xe_guc_pc *pc); int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc); int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode); int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc); +void xe_guc_pc_print(struct xe_guc_pc *pc, struct drm_printer *p); u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc); int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq); -- cgit v1.2.3-59-g8ed1b From 50554bf3e56dd0c78ef1eedb685d0ab36c9c9987 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 15 Jan 2025 09:50:53 -0500 Subject: drm/xe/lnl: Enable GuC SLPC DCC task Enable DCC (Duty Cycle Control) in Lunar Lake. DCC is the SLPC task that tries to keep the GT from operating inefficiently when thermally constrained. Although the recommendation is to enable it, LNL GuC is leaving it disabled by default on LNL. It would minimize the GT frequency oscillation on throttled scenarios, which could potentially reduce latencies. v2: Move set_policies call after wait for running state, so we ensure it is not overwritten. (Vinay) v3: Fix English in the commit message (Jonathan) v4: Also set disable to 0 so DCC can really get into effect. v5: Avoid lnl_ prefix (Vinay) v6: Finish renaming... Reviewed-by: Vinay Belgaumkar Reviewed-by: Jonathan Cavitt #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20250115145053.1142023-2-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc_pc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index 43f9617baba2..44b5211066ef 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -993,6 +993,27 @@ out: return ret; } +static int slpc_enable_dcc(struct xe_guc_pc *pc) +{ + int ret; + + ret = pc_action_set_param(pc, SLPC_PARAM_TASK_ENABLE_DCC, 1); + if (ret) + return ret; + + return pc_action_set_param(pc, SLPC_PARAM_TASK_DISABLE_DCC, 0); +} + +static int slpc_set_policies(struct xe_guc_pc *pc) +{ + struct xe_device *xe = pc_to_xe(pc); + + if (xe->info.platform == XE_LUNARLAKE) + return slpc_enable_dcc(pc); + + return 0; +} + /** * xe_guc_pc_start - Start GuC's Power Conservation component * @pc: Xe_GuC_PC instance @@ -1037,6 +1058,10 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) goto out; } + ret = slpc_set_policies(pc); + if (ret) + goto out; + ret = pc_init_freqs(pc); if (ret) goto out; -- cgit v1.2.3-59-g8ed1b From 11a64adcdbcc3028b96e440bc33fa76e2e825c10 Mon Sep 17 00:00:00 2001 From: Francois Dugast Date: Tue, 14 Jan 2025 12:38:53 -0800 Subject: drm/xe/xe3: Generate and store the L3 bank mask On Xe3, the register used to indicate which L3 banks are enabled on the system is a new one called MIRROR_L3BANK_ENABLE. Each bit represents one bank enabled in each node. Extend the existing topology code for Xe3 to read this register and generate the correct L3 bank mask, which can be read by user space throug the topology query. Bspec: 72573, 73439 Signed-off-by: Francois Dugast Signed-off-by: Matt Atwood Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20250114203853.35055-1-matthew.s.atwood@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 3 +++ drivers/gpu/drm/xe/xe_gt_topology.c | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index b4283ac030f4..096859072396 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -221,6 +221,9 @@ #define MIRROR_FUSE1 XE_REG(0x911c) +#define MIRROR_L3BANK_ENABLE XE_REG(0x9130) +#define XE3_L3BANK_ENABLE REG_GENMASK(31, 0) + #define XELP_EU_ENABLE XE_REG(0x9134) /* "_DISABLE" on Xe_LP */ #define XELP_EU_MASK REG_GENMASK(7, 0) #define XELP_GT_SLICE_ENABLE XE_REG(0x9138) diff --git a/drivers/gpu/drm/xe/xe_gt_topology.c b/drivers/gpu/drm/xe/xe_gt_topology.c index df2042db7ee6..516c81e3b8dd 100644 --- a/drivers/gpu/drm/xe/xe_gt_topology.c +++ b/drivers/gpu/drm/xe/xe_gt_topology.c @@ -129,7 +129,8 @@ static void load_l3_bank_mask(struct xe_gt *gt, xe_l3_bank_mask_t l3_bank_mask) { struct xe_device *xe = gt_to_xe(gt); - u32 fuse3 = xe_mmio_read32(>->mmio, MIRROR_FUSE3); + struct xe_mmio *mmio = >->mmio; + u32 fuse3 = xe_mmio_read32(mmio, MIRROR_FUSE3); /* * PTL platforms with media version 30.00 do not provide proper values @@ -143,7 +144,16 @@ load_l3_bank_mask(struct xe_gt *gt, xe_l3_bank_mask_t l3_bank_mask) if (XE_WA(gt, no_media_l3)) return; - if (GRAPHICS_VER(xe) >= 20) { + if (GRAPHICS_VER(xe) >= 30) { + xe_l3_bank_mask_t per_node = {}; + u32 meml3_en = REG_FIELD_GET(XE2_NODE_ENABLE_MASK, fuse3); + u32 mirror_l3bank_enable = xe_mmio_read32(mmio, MIRROR_L3BANK_ENABLE); + u32 bank_val = REG_FIELD_GET(XE3_L3BANK_ENABLE, mirror_l3bank_enable); + + bitmap_from_arr32(per_node, &bank_val, 32); + gen_l3_mask_from_pattern(xe, l3_bank_mask, per_node, 32, + meml3_en); + } else if (GRAPHICS_VER(xe) >= 20) { xe_l3_bank_mask_t per_node = {}; u32 meml3_en = REG_FIELD_GET(XE2_NODE_ENABLE_MASK, fuse3); u32 bank_val = REG_FIELD_GET(XE2_GT_L3_MODE_MASK, fuse3); @@ -155,7 +165,7 @@ load_l3_bank_mask(struct xe_gt *gt, xe_l3_bank_mask_t l3_bank_mask) xe_l3_bank_mask_t per_node = {}; xe_l3_bank_mask_t per_mask_bit = {}; u32 meml3_en = REG_FIELD_GET(MEML3_EN_MASK, fuse3); - u32 fuse4 = xe_mmio_read32(>->mmio, XEHP_FUSE4); + u32 fuse4 = xe_mmio_read32(mmio, XEHP_FUSE4); u32 bank_val = REG_FIELD_GET(GT_L3_EXC_MASK, fuse4); bitmap_set_value8(per_mask_bit, 0x3, 0); -- cgit v1.2.3-59-g8ed1b From 174e9ce0daf6af791386e96e76e743eb59e8a401 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 13 Jan 2025 11:44:04 -0800 Subject: drm/xe/guc: Drop error messages about missing GuC logs The GuC log snapshot code would complain loudly if there was no GuC log to take a snapshot of or if the snapshot alloc failed. Originally, this code was only called on demand when a user (or developer) explicitly requested a dump of the log. Hence an error message was useful. However, it is now part of the general devcoredump file and is called for any GPU hang. Most people don't care about GuC logs and GPU hangs do not generally mean a kernel/GuC bug. More importantly, there are valid situations where there is no GuC log, e.g. SRIOV VFs. So drop the error message. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/3958 Signed-off-by: John Harrison Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250113194405.2033085-1-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/xe_guc_log.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c index df4cfb698cdb..80151ff6a71f 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.c +++ b/drivers/gpu/drm/xe/xe_guc_log.c @@ -149,16 +149,12 @@ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, size_t remain; int i; - if (!log->bo) { - xe_gt_err(gt, "GuC log buffer not allocated\n"); + if (!log->bo) return NULL; - } snapshot = xe_guc_log_snapshot_alloc(log, atomic); - if (!snapshot) { - xe_gt_err(gt, "GuC log snapshot not allocated\n"); + if (!snapshot) return NULL; - } remain = snapshot->size; for (i = 0; i < snapshot->num_chunks; i++) { -- cgit v1.2.3-59-g8ed1b From 1e14484677c8e87548f5f0d4eb8800e408004404 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Wed, 15 Jan 2025 11:01:37 +0000 Subject: drm/ssd130x: fix ssd132x encoding The ssd132x buffer is encoded one pixel per nibble, with two pixels in each byte. When encoding an 8-bit greyscale input, take the top 4-bits as the value and ensure the two pixels are distinct and do not overwrite each other. Fixes: fdd591e00a9c ("drm/ssd130x: Add support for the SSD132x OLED controller family") Signed-off-by: John Keeping Reviewed-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20250115110139.1672488-2-jkeeping@inmusicbrands.com Signed-off-by: Javier Martinez Canillas --- drivers/gpu/drm/solomon/ssd130x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index b777690fd660..4bb663f984ce 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -880,7 +880,7 @@ static int ssd132x_update_rect(struct ssd130x_device *ssd130x, u8 n1 = buf[i * width + j]; u8 n2 = buf[i * width + j + 1]; - data_array[array_idx++] = (n2 << 4) | n1; + data_array[array_idx++] = (n2 & 0xf0) | (n1 >> 4); } } -- cgit v1.2.3-59-g8ed1b From 229adcffdb54b13332d2afd2dc5d203418d50908 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Wed, 15 Jan 2025 11:01:38 +0000 Subject: drm/ssd130x: ensure ssd132x pitch is correct The bounding rectangle is adjusted to ensure it aligns to SSD132X_SEGMENT_WIDTH, which may adjust the pitch. Calculate the pitch after aligning the left and right edge. Fixes: fdd591e00a9c ("drm/ssd130x: Add support for the SSD132x OLED controller family") Signed-off-by: John Keeping Reviewed-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20250115110139.1672488-3-jkeeping@inmusicbrands.com Signed-off-by: Javier Martinez Canillas --- drivers/gpu/drm/solomon/ssd130x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 4bb663f984ce..dd2006d51c7a 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -1037,7 +1037,7 @@ static int ssd132x_fb_blit_rect(struct drm_framebuffer *fb, struct drm_format_conv_state *fmtcnv_state) { struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev); - unsigned int dst_pitch = drm_rect_width(rect); + unsigned int dst_pitch; struct iosys_map dst; int ret = 0; @@ -1046,6 +1046,8 @@ static int ssd132x_fb_blit_rect(struct drm_framebuffer *fb, rect->x2 = min_t(unsigned int, round_up(rect->x2, SSD132X_SEGMENT_WIDTH), ssd130x->width); + dst_pitch = drm_rect_width(rect); + ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); if (ret) return ret; -- cgit v1.2.3-59-g8ed1b From 440aaf479c9aaf5ecea9a463eb826ec243d5f1cf Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 14 Jan 2025 10:59:42 +0000 Subject: drm/sched: Remove weak paused submission checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to check the boolean in the work item's prologues since the boolean can be set at any later time anyway. The helper which pauses submission sets it and synchronously cancels the work and helpers which queue the work check for the flag so all should be good. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250114105942.64832-1-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/scheduler/sched_main.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 81d69c2ff6ab..d172e3158880 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -1153,9 +1153,6 @@ static void drm_sched_free_job_work(struct work_struct *w) container_of(w, struct drm_gpu_scheduler, work_free_job); struct drm_sched_job *job; - if (READ_ONCE(sched->pause_submit)) - return; - job = drm_sched_get_finished_job(sched); if (job) sched->ops->free_job(job); @@ -1179,9 +1176,6 @@ static void drm_sched_run_job_work(struct work_struct *w) struct drm_sched_job *sched_job; int r; - if (READ_ONCE(sched->pause_submit)) - return; - /* Find entity with a ready job */ entity = drm_sched_select_entity(sched); if (!entity) -- cgit v1.2.3-59-g8ed1b From 75d37750a753e7ae079e470ea9699caeae756e3d Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Mon, 13 Jan 2025 17:12:01 +0530 Subject: drm/xe/mmap: Add mmap support for PCI memory barrier In order to avoid having userspace to use MI_MEM_FENCE, we are adding a mechanism for userspace to generate a PCI memory barrier with low overhead (avoiding IOCTL call as well as writing to VRAM will adds some overhead). This is implemented by memory-mapping a page as uncached that is backed by MMIO on the dGPU and thus allowing userspace to do memory write to the page without invoking an IOCTL. We are selecting the MMIO so that it is not accessible from the PCI bus so that the MMIO writes themselves are ignored, but the PCI memory barrier will still take action as the MMIO filtering will happen after the memory barrier effect. When we detect special defined offset in mmap(), We are mapping 4K page which contains the last of page of doorbell MMIO range to userspace for same purpose. For user to query special offset we are adding special flag in mmap_offset ioctl which needs to be passed as follows, struct drm_xe_gem_mmap_offset mmo = { .handle = 0, /* this must be 0 */ .flags = DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER, }; igt_ioctl(fd, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmo); map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mmo); IGT : https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/commit/b2dbc6f22815128c0dd5c737504f42e1f1a6ad62 UMD : https://github.com/intel/compute-runtime/pull/772 V7: - Dgpu filter added V6(MAuld) - Move physical mmap to fault handler - Modify kernel-doc and attach UMD PR when ready V5(MAuld) - Return invalid early in case of non 4K PAGE_SIZE - Format kernel-doc and add note for 4K PAGE_SIZE HW limit V4(MAuld) - Add kernel-doc for uapi change - Restrict page size to 4K V3(MAuld) - Remove offset defination from UAPI to be able to change later - Edit commit message for special flag addition V2(MAuld) - Add fault handler with dummy page to handle unplug device - Add Build check for special offset to be below normal start page - Test d3hot, mapping seems to be valid in d3hot as well - Add more info to commit message Cc: Matthew Auld Acked-by: Michal Mrozek Reviewed-by: Matthew Auld Signed-off-by: Tejas Upadhyay Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20250113114201.3178806-1-tejas.upadhyay@intel.com --- drivers/gpu/drm/xe/xe_bo.c | 19 +++++++- drivers/gpu/drm/xe/xe_bo.h | 2 + drivers/gpu/drm/xe/xe_device.c | 107 ++++++++++++++++++++++++++++++++++++++++- include/uapi/drm/xe_drm.h | 29 ++++++++++- 4 files changed, 154 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 4f077c11e8e2..78d19fd4670a 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2278,9 +2278,26 @@ int xe_gem_mmap_offset_ioctl(struct drm_device *dev, void *data, XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1])) return -EINVAL; - if (XE_IOCTL_DBG(xe, args->flags)) + if (XE_IOCTL_DBG(xe, args->flags & + ~DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER)) return -EINVAL; + if (args->flags & DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER) { + if (XE_IOCTL_DBG(xe, !IS_DGFX(xe))) + return -EINVAL; + + if (XE_IOCTL_DBG(xe, args->handle)) + return -EINVAL; + + if (XE_IOCTL_DBG(xe, PAGE_SIZE > SZ_4K)) + return -EINVAL; + + BUILD_BUG_ON(((XE_PCI_BARRIER_MMAP_OFFSET >> XE_PTE_SHIFT) + + SZ_4K) >= DRM_FILE_PAGE_OFFSET_START); + args->offset = XE_PCI_BARRIER_MMAP_OFFSET; + return 0; + } + gem_obj = drm_gem_object_lookup(file, args->handle); if (XE_IOCTL_DBG(xe, !gem_obj)) return -ENOENT; diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h index d9386ab03140..04995c5ced32 100644 --- a/drivers/gpu/drm/xe/xe_bo.h +++ b/drivers/gpu/drm/xe/xe_bo.h @@ -75,6 +75,8 @@ #define XE_BO_PROPS_INVALID (-1) +#define XE_PCI_BARRIER_MMAP_OFFSET (0x50 << XE_PTE_SHIFT) + struct sg_table; struct xe_bo *xe_bo_alloc(void); diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 5cbc96b214fe..6ecbf7dd396c 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -232,12 +232,117 @@ static long xe_drm_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo #define xe_drm_compat_ioctl NULL #endif +static void barrier_open(struct vm_area_struct *vma) +{ + drm_dev_get(vma->vm_private_data); +} + +static void barrier_close(struct vm_area_struct *vma) +{ + drm_dev_put(vma->vm_private_data); +} + +static void barrier_release_dummy_page(struct drm_device *dev, void *res) +{ + struct page *dummy_page = (struct page *)res; + + __free_page(dummy_page); +} + +static vm_fault_t barrier_fault(struct vm_fault *vmf) +{ + struct drm_device *dev = vmf->vma->vm_private_data; + struct vm_area_struct *vma = vmf->vma; + vm_fault_t ret = VM_FAULT_NOPAGE; + pgprot_t prot; + int idx; + + prot = vm_get_page_prot(vma->vm_flags); + + if (drm_dev_enter(dev, &idx)) { + unsigned long pfn; + +#define LAST_DB_PAGE_OFFSET 0x7ff001 + pfn = PHYS_PFN(pci_resource_start(to_pci_dev(dev->dev), 0) + + LAST_DB_PAGE_OFFSET); + ret = vmf_insert_pfn_prot(vma, vma->vm_start, pfn, + pgprot_noncached(prot)); + drm_dev_exit(idx); + } else { + struct page *page; + + /* Allocate new dummy page to map all the VA range in this VMA to it*/ + page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!page) + return VM_FAULT_OOM; + + /* Set the page to be freed using drmm release action */ + if (drmm_add_action_or_reset(dev, barrier_release_dummy_page, page)) + return VM_FAULT_OOM; + + ret = vmf_insert_pfn_prot(vma, vma->vm_start, page_to_pfn(page), + prot); + } + + return ret; +} + +static const struct vm_operations_struct vm_ops_barrier = { + .open = barrier_open, + .close = barrier_close, + .fault = barrier_fault, +}; + +static int xe_pci_barrier_mmap(struct file *filp, + struct vm_area_struct *vma) +{ + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + struct xe_device *xe = to_xe_device(dev); + + if (!IS_DGFX(xe)) + return -EINVAL; + + if (vma->vm_end - vma->vm_start > SZ_4K) + return -EINVAL; + + if (is_cow_mapping(vma->vm_flags)) + return -EINVAL; + + if (vma->vm_flags & (VM_READ | VM_EXEC)) + return -EINVAL; + + vm_flags_clear(vma, VM_MAYREAD | VM_MAYEXEC); + vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_IO); + vma->vm_ops = &vm_ops_barrier; + vma->vm_private_data = dev; + drm_dev_get(vma->vm_private_data); + + return 0; +} + +static int xe_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + + if (drm_dev_is_unplugged(dev)) + return -ENODEV; + + switch (vma->vm_pgoff) { + case XE_PCI_BARRIER_MMAP_OFFSET >> XE_PTE_SHIFT: + return xe_pci_barrier_mmap(filp, vma); + } + + return drm_gem_mmap(filp, vma); +} + static const struct file_operations xe_driver_fops = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release_noglobal, .unlocked_ioctl = xe_drm_ioctl, - .mmap = drm_gem_mmap, + .mmap = xe_mmap, .poll = drm_poll, .read = drm_read, .compat_ioctl = xe_drm_compat_ioctl, diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index f62689ca861a..cac607a30f6d 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -811,6 +811,32 @@ struct drm_xe_gem_create { /** * struct drm_xe_gem_mmap_offset - Input of &DRM_IOCTL_XE_GEM_MMAP_OFFSET + * + * The @flags can be: + * - %DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER - For user to query special offset + * for use in mmap ioctl. Writing to the returned mmap address will generate a + * PCI memory barrier with low overhead (avoiding IOCTL call as well as writing + * to VRAM which would also add overhead), acting like an MI_MEM_FENCE + * instruction. + * + * Note: The mmap size can be at most 4K, due to HW limitations. As a result + * this interface is only supported on CPU architectures that support 4K page + * size. The mmap_offset ioctl will detect this and gracefully return an + * error, where userspace is expected to have a different fallback method for + * triggering a barrier. + * + * Roughly the usage would be as follows: + * + * .. code-block:: C + * + * struct drm_xe_gem_mmap_offset mmo = { + * .handle = 0, // must be set to 0 + * .flags = DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER, + * }; + * + * err = ioctl(fd, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmo); + * map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mmo.offset); + * map[i] = 0xdeadbeaf; // issue barrier */ struct drm_xe_gem_mmap_offset { /** @extensions: Pointer to the first extension struct, if any */ @@ -819,7 +845,8 @@ struct drm_xe_gem_mmap_offset { /** @handle: Handle for the object being mapped. */ __u32 handle; - /** @flags: Must be zero */ +#define DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER (1 << 0) + /** @flags: Flags */ __u32 flags; /** @offset: The fake offset to use for subsequent mmap call */ -- cgit v1.2.3-59-g8ed1b From 758debf35b9cda5450e40996991a6e4b222899bd Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 13 Jan 2025 16:25:07 -0800 Subject: drm/xe: Mark ComputeCS read mode as UC on iGPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RING_CMD_CCTL read index should be UC on iGPU parts due to L3 caching structure. Having this as WB blocks ULLS from being enabled. Change to UC to unblock ULLS on iGPU. v2: - Drop internal communications commnet, bspec is updated Cc: Balasubramani Vivekanandan Cc: Michal Mrozek Cc: Paulo Zanoni Cc: José Roberto de Souza Cc: stable@vger.kernel.org Fixes: 328e089bfb37 ("drm/xe: Leverage ComputeCS read L3 caching") Signed-off-by: Matthew Brost Acked-by: Michal Mrozek Reviewed-by: Stuart Summers Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20250114002507.114087-1-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_hw_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index ac9c666a9652..fc447751fe78 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -422,7 +422,7 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) * Bspec: 72161 */ const u8 mocs_write_idx = gt->mocs.uc_index; - const u8 mocs_read_idx = hwe->class == XE_ENGINE_CLASS_COMPUTE && + const u8 mocs_read_idx = hwe->class == XE_ENGINE_CLASS_COMPUTE && IS_DGFX(xe) && (GRAPHICS_VER(xe) >= 20 || xe->info.platform == XE_PVC) ? gt->mocs.wb_index : gt->mocs.uc_index; u32 ring_cmd_cctl_val = REG_FIELD_PREP(CMD_CCTL_WRITE_OVERRIDE_MASK, mocs_write_idx) | -- cgit v1.2.3-59-g8ed1b From 63060df6f709cbe494f0cfcaa613655862ba479a Mon Sep 17 00:00:00 2001 From: Oak Zeng Date: Wed, 18 Dec 2024 11:48:31 -0500 Subject: drm/xe: trace bo create Add a tracepoint to trace bo create. Signed-off-by: Oak Zeng Reviewed-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20241218164833.2364049-2-oak.zeng@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_bo.c | 1 + drivers/gpu/drm/xe/xe_trace_bo.h | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 78d19fd4670a..cf0dc9e9c53e 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -1659,6 +1659,7 @@ __xe_bo_create_locked(struct xe_device *xe, } } + trace_xe_bo_create(bo); return bo; err_unlock_put_bo: diff --git a/drivers/gpu/drm/xe/xe_trace_bo.h b/drivers/gpu/drm/xe/xe_trace_bo.h index ea50fee50c7d..3d7e6c80b0aa 100644 --- a/drivers/gpu/drm/xe/xe_trace_bo.h +++ b/drivers/gpu/drm/xe/xe_trace_bo.h @@ -53,6 +53,11 @@ DEFINE_EVENT(xe_bo, xe_bo_validate, TP_ARGS(bo) ); +DEFINE_EVENT(xe_bo, xe_bo_create, + TP_PROTO(struct xe_bo *bo), + TP_ARGS(bo) +); + TRACE_EVENT(xe_bo_move, TP_PROTO(struct xe_bo *bo, uint32_t new_placement, uint32_t old_placement, bool move_lacks_source), -- cgit v1.2.3-59-g8ed1b From 861b27584d9055e4e1763341474ce8ce9dc6a55d Mon Sep 17 00:00:00 2001 From: Oak Zeng Date: Wed, 18 Dec 2024 11:48:32 -0500 Subject: drm/xe: Print vm flags in xe_vm trace print Print vm flags in xe_vm trace print. This is helpful to diagnosis the VM mode of operation. Signed-off-by: Oak Zeng Reviewed-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20241218164833.2364049-3-oak.zeng@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_trace_bo.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_trace_bo.h b/drivers/gpu/drm/xe/xe_trace_bo.h index 3d7e6c80b0aa..082fadb5f99b 100644 --- a/drivers/gpu/drm/xe/xe_trace_bo.h +++ b/drivers/gpu/drm/xe/xe_trace_bo.h @@ -190,16 +190,19 @@ DECLARE_EVENT_CLASS(xe_vm, __string(dev, __dev_name_vm(vm)) __field(struct xe_vm *, vm) __field(u32, asid) + __field(u32, flags) ), TP_fast_assign( __assign_str(dev); __entry->vm = vm; __entry->asid = vm->usm.asid; + __entry->flags = vm->flags; ), - TP_printk("dev=%s, vm=%p, asid=0x%05x", __get_str(dev), - __entry->vm, __entry->asid) + TP_printk("dev=%s, vm=%p, asid=0x%05x, vm flags=0x%05x", + __get_str(dev), __entry->vm, __entry->asid, + __entry->flags) ); DEFINE_EVENT(xe_vm, xe_vm_kill, -- cgit v1.2.3-59-g8ed1b From 22b1a53f282b1ad6692c6238a7446275854f0afb Mon Sep 17 00:00:00 2001 From: Oak Zeng Date: Wed, 18 Dec 2024 11:48:33 -0500 Subject: drm/xe: Print vm parameter in xe_vma trace Print the vm that the vma belongs to in the vma trace. This is useful to correlate VMA operations to the VM. Signed-off-by: Oak Zeng Reviewed-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20241218164833.2364049-4-oak.zeng@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_trace_bo.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_trace_bo.h b/drivers/gpu/drm/xe/xe_trace_bo.h index 082fadb5f99b..ccebd5f0878e 100644 --- a/drivers/gpu/drm/xe/xe_trace_bo.h +++ b/drivers/gpu/drm/xe/xe_trace_bo.h @@ -92,6 +92,7 @@ DECLARE_EVENT_CLASS(xe_vma, TP_STRUCT__entry( __string(dev, __dev_name_vma(vma)) __field(struct xe_vma *, vma) + __field(struct xe_vm *, vm) __field(u32, asid) __field(u64, start) __field(u64, end) @@ -101,14 +102,16 @@ DECLARE_EVENT_CLASS(xe_vma, TP_fast_assign( __assign_str(dev); __entry->vma = vma; + __entry->vm = xe_vma_vm(vma); __entry->asid = xe_vma_vm(vma)->usm.asid; __entry->start = xe_vma_start(vma); __entry->end = xe_vma_end(vma) - 1; __entry->ptr = xe_vma_userptr(vma); ), - TP_printk("dev=%s, vma=%p, asid=0x%05x, start=0x%012llx, end=0x%012llx, userptr=0x%012llx,", - __get_str(dev), __entry->vma, __entry->asid, __entry->start, + TP_printk("dev=%s, vma=%p, vm=%p, asid=0x%05x, start=0x%012llx, end=0x%012llx, userptr=0x%012llx", + __get_str(dev), __entry->vma, __entry->vm, + __entry->asid, __entry->start, __entry->end, __entry->ptr) ) -- cgit v1.2.3-59-g8ed1b From b824709ee1d0dbfed4b1757279c97fc0edad1e1a Mon Sep 17 00:00:00 2001 From: Oak Zeng Date: Mon, 13 Jan 2025 16:23:24 -0500 Subject: drm/xe: Fix a typo in xe_vm_doc.h s/vm->ttm.base.resv->lock/vm->gpuvm.r_obj->resv->lock Signed-off-by: Oak Zeng Reviewed-by: Maciej Patelczyk Link: https://patchwork.freedesktop.org/patch/msgid/20250113212324.3264218-1-oak.zeng@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm_doc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_vm_doc.h b/drivers/gpu/drm/xe/xe_vm_doc.h index 078786958403..1030ce214032 100644 --- a/drivers/gpu/drm/xe/xe_vm_doc.h +++ b/drivers/gpu/drm/xe/xe_vm_doc.h @@ -431,7 +431,7 @@ * bind path also acquires this lock in write while the exec / compute mode * rebind worker acquires this lock in read mode. * - * VM dma-resv lock (vm->ttm.base.resv->lock) - WW lock. Protects VM dma-resv + * VM dma-resv lock (vm->gpuvm.r_obj->resv->lock) - WW lock. Protects VM dma-resv * slots which is shared with any private BO in the VM. Expected to be acquired * during VM binds, execs, and compute mode rebind worker. This lock is also * held when private BOs are being evicted. -- cgit v1.2.3-59-g8ed1b From 73900dce57e40bcced9af4518051ab9dabb9aea9 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 14 Jan 2025 14:28:57 +0200 Subject: drm/xe/dp: Enable DP tunneling Enable the DP tunneling functionality in the xe driver. v2: Keep using IS_ENABLED() for kconfig options. (Jani) Cc: Jani Nikula Reviewed-by: Suraj Kandpal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250114122857.1050090-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_tunnel.h | 5 +++-- drivers/gpu/drm/xe/Kconfig | 14 ++++++++++++++ drivers/gpu/drm/xe/Makefile | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.h b/drivers/gpu/drm/i915/display/intel_dp_tunnel.h index e9314cf25a19..7f0f720e8dca 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.h +++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.h @@ -20,7 +20,8 @@ struct intel_dp; struct intel_encoder; struct intel_link_bw_limits; -#if IS_ENABLED(CONFIG_DRM_I915_DP_TUNNEL) && defined(I915) +#if (IS_ENABLED(CONFIG_DRM_I915_DP_TUNNEL) && defined(I915)) || \ + (IS_ENABLED(CONFIG_DRM_XE_DP_TUNNEL) && !defined(I915)) int intel_dp_tunnel_detect(struct intel_dp *intel_dp, struct drm_modeset_acquire_ctx *ctx); void intel_dp_tunnel_disconnect(struct intel_dp *intel_dp); @@ -127,6 +128,6 @@ intel_dp_tunnel_mgr_init(struct intel_display *display) static inline void intel_dp_tunnel_mgr_cleanup(struct intel_display *display) {} -#endif /* CONFIG_DRM_I915_DP_TUNNEL */ +#endif /* CONFIG_DRM_I915_DP_TUNNEL || CONFIG_DRM_XE_DP_TUNNEL */ #endif /* __INTEL_DP_TUNNEL_H__ */ diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index b51a2bde73e2..50cf80df5190 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -59,6 +59,20 @@ config DRM_XE_DISPLAY help Disable this option only if you want to compile out display support. +config DRM_XE_DP_TUNNEL + bool "Enable DP tunnel support" + depends on DRM_XE + depends on USB4 + select DRM_DISPLAY_DP_TUNNEL + default y + help + Choose this option to detect DP tunnels and enable the Bandwidth + Allocation mode for such tunnels. This allows using the maximum + resolution allowed by the link BW on all displays sharing the + link BW, for instance on a Thunderbolt link. + + If in doubt say "Y". + config DRM_XE_FORCE_PROBE string "Force probe xe for selected Intel hardware IDs" depends on DRM_XE diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 5c97ad6ed738..81f63258a7e1 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -301,6 +301,9 @@ ifeq ($(CONFIG_DEBUG_FS),y) i915-display/intel_pipe_crc.o endif +xe-$(CONFIG_DRM_XE_DP_TUNNEL) += \ + i915-display/intel_dp_tunnel.o + obj-$(CONFIG_DRM_XE) += xe.o obj-$(CONFIG_DRM_XE_KUNIT_TEST) += tests/ -- cgit v1.2.3-59-g8ed1b From e35ecd95ecf28478c6aeac1ab480bbc033dae9c9 Mon Sep 17 00:00:00 2001 From: Dnyaneshwar Bhadane Date: Wed, 18 Dec 2024 01:43:00 +0530 Subject: drm/i915/display: Add MTL subplatforms definition Separate MTL-U platform PCI ids in one define macro. Add the MTL U/ARL U as subplatform member in MTL platform description structure to use display.platform. from intel_display structure instead of IS_() in display code path. v2: - Club ARL-u in MTL and identify ARL-u as MTL-u subplatform(Jani) Signed-off-by: Dnyaneshwar Bhadane Reviewed-by: Suraj Kandpal Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20241217201301.3593054-2-dnyaneshwar.bhadane@intel.com --- drivers/gpu/drm/i915/display/intel_display_device.c | 13 +++++++++++++ drivers/gpu/drm/i915/display/intel_display_device.h | 1 + include/drm/intel/pciids.h | 7 +++++-- 3 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index 68cb7f9b9ef3..738ae522c8f4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -1357,6 +1357,12 @@ static const struct intel_display_device_info xe2_hpd_display = { BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4), }; +static const u16 mtl_u_ids[] = { + INTEL_MTL_U_IDS(ID), + INTEL_ARL_U_IDS(ID), + 0 +}; + /* * Do not initialize the .info member of the platform desc for GMD ID based * platforms. Their display will be probed automatically based on the IP version @@ -1364,6 +1370,13 @@ static const struct intel_display_device_info xe2_hpd_display = { */ static const struct platform_desc mtl_desc = { PLATFORM(meteorlake), + .subplatforms = (const struct subplatform_desc[]) { + { + SUBPLATFORM(meteorlake, u), + .pciidlist = mtl_u_ids, + }, + {}, + } }; static const struct platform_desc lnl_desc = { diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 9a333d9e6601..5853472bb9c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -96,6 +96,7 @@ struct pci_dev; func(dg2_g12) \ /* Display ver 14 (based on GMD ID) */ \ func(meteorlake) \ + func(meteorlake_u) \ /* Display ver 20 (based on GMD ID) */ \ func(lunarlake) \ /* Display ver 14.1 (based on GMD ID) */ \ diff --git a/include/drm/intel/pciids.h b/include/drm/intel/pciids.h index c6518b0992cf..46b05fa1f903 100644 --- a/include/drm/intel/pciids.h +++ b/include/drm/intel/pciids.h @@ -811,9 +811,12 @@ INTEL_ARL_S_IDS(MACRO__, ## __VA_ARGS__) /* MTL */ -#define INTEL_MTL_IDS(MACRO__, ...) \ +#define INTEL_MTL_U_IDS(MACRO__, ...) \ MACRO__(0x7D40, ## __VA_ARGS__), \ - MACRO__(0x7D45, ## __VA_ARGS__), \ + MACRO__(0x7D45, ## __VA_ARGS__) + +#define INTEL_MTL_IDS(MACRO__, ...) \ + INTEL_MTL_U_IDS(MACRO__, ## __VA_ARGS__), \ MACRO__(0x7D55, ## __VA_ARGS__), \ MACRO__(0x7D60, ## __VA_ARGS__), \ MACRO__(0x7DD5, ## __VA_ARGS__) -- cgit v1.2.3-59-g8ed1b From 3630a47b700e65066d3c9a3b6a58af5bfca812e9 Mon Sep 17 00:00:00 2001 From: Dnyaneshwar Bhadane Date: Wed, 18 Dec 2024 01:43:01 +0530 Subject: drm/i915/cx0_phy: Update HDMI TMDS C20 algorithm value In the C20 algorithm for HDMI TMDS, certain fields have been updated in the BSpec to set values for SRAM_GENERIC__TX_CNTX_CFG_1, such as tx_misc and dac_ctrl_range for Xe2LPD, Xe2HPD and MTL/ARL. This patch covers fields that need to be set based on the platform type. Some ARLs SoCs cannot be directly distinguished by their GMD version Id, Specifically to set value of tx_misc, so PCI Host Bridge IDs are used for differentiation. v2: - Relocate defines and Restructure the code(Jani) v3: - Replace conditions with display.platform. (jani) - Move host bridge check to new function (Jani) v4: - Identify/Replace arrowlake_u as meteorlake_u(Jani) Bspec:74165,74491 Signed-off-by: Dnyaneshwar Bhadane Reviewed-by: Suraj Kandpal Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20241217201301.3593054-3-dnyaneshwar.bhadane@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 48 ++++++++++++++++++---- drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h | 6 +++ .../gpu/drm/i915/display/intel_display_device.h | 11 +++++ 3 files changed, 57 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 5ebc90d210d4..857262fcbac9 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2173,9 +2173,47 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display, i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]); } -static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) +/* + * Some ARLs SoCs have the same drm PCI IDs, so need a helper to differentiate based + * on the host bridge device ID to get the correct txx_mics value. + */ +static bool is_arrowlake_s_by_host_bridge(void) +{ + struct pci_dev *pdev = NULL; + u16 host_bridge_pci_dev_id; + + while ((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, pdev))) + host_bridge_pci_dev_id = pdev->device; + + return pdev && IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(host_bridge_pci_dev_id); +} + +static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); + u16 tx_misc; + u16 tx_dcc_cal_dac_ctrl_range = 8; + u16 tx_term_ctrl = 2; + + if (DISPLAY_VER(display) >= 20) { + tx_misc = 5; + tx_term_ctrl = 4; + } else if (display->platform.battlemage) { + tx_misc = 0; + } else if (display->platform.meteorlake_u || + is_arrowlake_s_by_host_bridge()) { + tx_misc = 3; + } else { + tx_misc = 7; + } + + return (C20_PHY_TX_MISC(tx_misc) | + C20_PHY_TX_DCC_CAL_RANGE(tx_dcc_cal_dac_ctrl_range) | + C20_PHY_TX_DCC_BYPASS | C20_PHY_TX_TERM_CTL(tx_term_ctrl)); +} + +static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) +{ struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20; u64 datarate; u64 mpll_tx_clk_div; @@ -2185,7 +2223,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) u64 mpll_multiplier; u64 mpll_fracn_quot; u64 mpll_fracn_rem; - u16 tx_misc; u8 mpllb_ana_freq_vco; u8 mpll_div_multiplier; @@ -2205,11 +2242,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) mpll_div_multiplier = min_t(u8, div64_u64((vco_freq * 16 + (datarate >> 1)), datarate), 255); - if (DISPLAY_VER(display) >= 20) - tx_misc = 0x5; - else - tx_misc = 0x0; - if (vco_freq <= DATARATE_3000000000) mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_3; else if (vco_freq <= DATARATE_3500000000) @@ -2221,7 +2253,7 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) pll_state->clock = crtc_state->port_clock; pll_state->tx[0] = 0xbe88; - pll_state->tx[1] = 0x9800 | C20_PHY_TX_MISC(tx_misc); + pll_state->tx[1] = intel_c20_hdmi_tmds_tx_cgf_1(crtc_state); pll_state->tx[2] = 0x0000; pll_state->cmn[0] = 0x0500; pll_state->cmn[1] = 0x0005; diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h index 4dc6e179a774..a47fd1aef9f0 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h @@ -294,6 +294,12 @@ #define C20_PHY_TX_RATE REG_GENMASK(2, 0) #define C20_PHY_TX_MISC_MASK REG_GENMASK16(7, 0) #define C20_PHY_TX_MISC(val) REG_FIELD_PREP16(C20_PHY_TX_MISC_MASK, (val)) +#define C20_PHY_TX_DCC_CAL_RANGE_MASK REG_GENMASK16(11, 8) +#define C20_PHY_TX_DCC_CAL_RANGE(val) \ + REG_FIELD_PREP16(C20_PHY_TX_DCC_CAL_RANGE_MASK, (val)) +#define C20_PHY_TX_DCC_BYPASS REG_BIT(12) +#define C20_PHY_TX_TERM_CTL_MASK REG_GENMASK16(15, 13) +#define C20_PHY_TX_TERM_CTL(val) REG_FIELD_PREP16(C20_PHY_TX_TERM_CTL_MASK, (val)) #define PHY_C20_A_CMN_CNTX_CFG(i915, idx) \ ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_CMN_CNTX_CFG : _MTL_C20_A_CMN_CNTX_CFG) - (idx)) diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 5853472bb9c2..a7b5ce69cf17 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -234,6 +234,17 @@ struct intel_display_platforms { (drm_WARN_ON(__to_intel_display(__display)->drm, INTEL_DISPLAY_STEP(__display) == STEP_NONE), \ INTEL_DISPLAY_STEP(__display) >= (since) && INTEL_DISPLAY_STEP(__display) < (until)) +#define ARLS_HOST_BRIDGE_PCI_ID1 0x7D1C +#define ARLS_HOST_BRIDGE_PCI_ID2 0x7D2D +#define ARLS_HOST_BRIDGE_PCI_ID3 0x7D2E +#define ARLS_HOST_BRIDGE_PCI_ID4 0x7D2F + +#define IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(id) \ + (((id) == ARLS_HOST_BRIDGE_PCI_ID1) || \ + ((id) == ARLS_HOST_BRIDGE_PCI_ID2) || \ + ((id) == ARLS_HOST_BRIDGE_PCI_ID3) || \ + ((id) == ARLS_HOST_BRIDGE_PCI_ID4)) + struct intel_display_runtime_info { struct intel_display_ip_ver { u16 ver; -- cgit v1.2.3-59-g8ed1b From 605a33e765890e4f1345315afc25268d4ae0fb7c Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Tue, 17 Dec 2024 14:07:23 +0530 Subject: drm/i915/hdcp: Fix Repeater authentication during topology change When topology changes, before beginning a new HDCP authentication by sending AKE_init message we need to first authenticate only the repeater. Only after repeater authentication failure, it makes sense to start a new HDCP authentication. Even though it made sense to not enable HDCP directly from check_link and schedule it for later, repeater authentication needs to be done immediately. --v2 -Fix comment grammatical errors [Ankit] Fixes: 47ef55a8b784 ("drm/i915/hdcp: Don't enable HDCP2.2 directly from check_link") Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20241217083723.2883317-1-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_hdcp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 7464b44c8bb3..c60b22aaa819 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2188,6 +2188,19 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) drm_dbg_kms(display->drm, "HDCP2.2 Downstream topology change\n"); + + ret = hdcp2_authenticate_repeater_topology(connector); + if (!ret) { + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_ENABLED, + true); + goto out; + } + + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] Repeater topology auth failed.(%d)\n", + connector->base.base.id, connector->base.name, + ret); } else { drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] HDCP2.2 link failed, retrying auth\n", -- cgit v1.2.3-59-g8ed1b From 3abe2824e1af16580ae669a037892eb9e7ad3d54 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 10 Jan 2025 10:11:30 +0530 Subject: drm/i915/dsc: Use helper to calculate range_bpg_offset We get range_bpg_offset for different bpps based on linear-interpolation from values given for nearby bpps. Use a helper to get these values. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Reviewed-by: Krzysztof Karas Link: https://patchwork.freedesktop.org/patch/msgid/20250110044131.3162682-2-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 59 ++++++++++++++++--------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index b355c479eda3..df07090c84eb 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -66,6 +66,13 @@ intel_vdsc_set_min_max_qp(struct drm_dsc_config *vdsc_cfg, int buf, intel_lookup_range_max_qp(bpc, buf, bpp, vdsc_cfg->native_420); } +static int +get_range_bpg_offset(int bpp_low, int offset_low, int bpp_high, int offset_high, int bpp) +{ + return offset_low + DIV_ROUND_UP((offset_high - offset_low) * (bpp - bpp_low), + (bpp_low - bpp_high)); +} + /* * We are using the method provided in DSC 1.2a C-Model in codec_main.c * Above method use a common formula to derive values for any combination of DSC @@ -83,7 +90,7 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg) int qp_bpc_modifier = (bpc - 8) * 2; int uncompressed_bpg_rate; int first_line_bpg_offset; - u32 res, buf_i, bpp_i; + u32 buf_i, bpp_i; if (vdsc_cfg->slice_height >= 8) first_line_bpg_offset = @@ -163,23 +170,19 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg) intel_vdsc_set_min_max_qp(vdsc_cfg, buf_i, bpp_i); /* Calculate range_bpg_offset */ - if (bpp <= 8) { + if (bpp <= 8) range_bpg_offset = ofs_und4[buf_i]; - } else if (bpp <= 10) { - res = DIV_ROUND_UP(((bpp - 8) * - (ofs_und5[buf_i] - ofs_und4[buf_i])), 2); - range_bpg_offset = ofs_und4[buf_i] + res; - } else if (bpp <= 12) { - res = DIV_ROUND_UP(((bpp - 10) * - (ofs_und6[buf_i] - ofs_und5[buf_i])), 2); - range_bpg_offset = ofs_und5[buf_i] + res; - } else if (bpp <= 16) { - res = DIV_ROUND_UP(((bpp - 12) * - (ofs_und8[buf_i] - ofs_und6[buf_i])), 4); - range_bpg_offset = ofs_und6[buf_i] + res; - } else { + else if (bpp <= 10) + range_bpg_offset = get_range_bpg_offset(8, ofs_und4[buf_i], + 10, ofs_und5[buf_i], bpp); + else if (bpp <= 12) + range_bpg_offset = get_range_bpg_offset(10, ofs_und5[buf_i], + 12, ofs_und6[buf_i], bpp); + else if (bpp <= 16) + range_bpg_offset = get_range_bpg_offset(12, ofs_und6[buf_i], + 16, ofs_und8[buf_i], bpp); + else range_bpg_offset = ofs_und8[buf_i]; - } vdsc_cfg->rc_range_params[buf_i].range_bpg_offset = range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK; @@ -215,21 +218,19 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg) intel_vdsc_set_min_max_qp(vdsc_cfg, buf_i, bpp_i); /* Calculate range_bpg_offset */ - if (bpp <= 6) { + if (bpp <= 6) range_bpg_offset = ofs_und6[buf_i]; - } else if (bpp <= 8) { - res = DIV_ROUND_UP(((bpp - 6) * - (ofs_und8[buf_i] - ofs_und6[buf_i])), 2); - range_bpg_offset = ofs_und6[buf_i] + res; - } else if (bpp <= 12) { - range_bpg_offset = ofs_und8[buf_i]; - } else if (bpp <= 15) { - res = DIV_ROUND_UP(((bpp - 12) * - (ofs_und15[buf_i] - ofs_und12[buf_i])), 3); - range_bpg_offset = ofs_und12[buf_i] + res; - } else { + else if (bpp <= 8) + range_bpg_offset = get_range_bpg_offset(6, ofs_und6[buf_i], + 8, ofs_und8[buf_i], bpp); + else if (bpp <= 12) + range_bpg_offset = get_range_bpg_offset(8, ofs_und8[buf_i], + 12, ofs_und12[buf_i], bpp); + else if (bpp <= 15) + range_bpg_offset = get_range_bpg_offset(12, ofs_und12[buf_i], + 15, ofs_und15[buf_i], bpp); + else range_bpg_offset = ofs_und15[buf_i]; - } vdsc_cfg->rc_range_params[buf_i].range_bpg_offset = range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK; -- cgit v1.2.3-59-g8ed1b From 0d69fc7a023b8a979fc8b2bd9cd0754a24abf99d Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 10 Jan 2025 10:11:31 +0530 Subject: drm/i915/dsc: Remove old comment about DSC 444 support DSC with YCbCr420 is now supported, so remove the comment mentioning support for only 444 format. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/20250110044131.3162682-3-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index df07090c84eb..1e8f71fb3094 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -124,7 +124,6 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg) vdsc_cfg->slice_height - 1); } - /* Our hw supports only 444 modes as of today */ if (bpp >= 12) vdsc_cfg->initial_offset = 2048; else if (bpp >= 10) -- cgit v1.2.3-59-g8ed1b From 58b7cd603db38d16350d380df70dbce468e99101 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Mon, 13 Jan 2025 17:38:56 -0300 Subject: drm/i915/display: Use display MMIO functions in intel_display_irq.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of MMIO accesses from intel_display_irq.c are currently done via uncore_*() functions instead of the display-specific ones, namely intel_de_*(). Because of that, DMC wakelock ends up being ignored and some invalid MMIO accesses are performed while display is in dynamic DC states. Thus, update the display IRQ code to use the intel_de_*() MMIO functions. After this change, we are left with some IRQ-specific functions that still use the unwrapped uncore_*() functions (i.e. gen2_irq_init, gen3_irq_reset and gen2_assert_iir_is_zero). We will deal with them in an upcoming change. Reviewed-by: Jouni Högander Signed-off-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20250113204306.112266-2-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/display/intel_display_irq.c | 222 ++++++++++++----------- 1 file changed, 121 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 069043f9d894..9662368a651d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -44,6 +44,7 @@ intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) void ilk_update_display_irq(struct drm_i915_private *dev_priv, u32 interrupt_mask, u32 enabled_irq_mask) { + struct intel_display *display = &dev_priv->display; u32 new_val; lockdep_assert_held(&dev_priv->irq_lock); @@ -56,8 +57,8 @@ void ilk_update_display_irq(struct drm_i915_private *dev_priv, if (new_val != dev_priv->irq_mask && !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { dev_priv->irq_mask = new_val; - intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask); - intel_uncore_posting_read(&dev_priv->uncore, DEIMR); + intel_de_write(display, DEIMR, dev_priv->irq_mask); + intel_de_posting_read(display, DEIMR); } } @@ -80,6 +81,7 @@ void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits) void bdw_update_port_irq(struct drm_i915_private *dev_priv, u32 interrupt_mask, u32 enabled_irq_mask) { + struct intel_display *display = &dev_priv->display; u32 new_val; u32 old_val; @@ -90,15 +92,15 @@ void bdw_update_port_irq(struct drm_i915_private *dev_priv, if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) return; - old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); + old_val = intel_de_read(display, GEN8_DE_PORT_IMR); new_val = old_val; new_val &= ~interrupt_mask; new_val |= (~enabled_irq_mask & interrupt_mask); if (new_val != old_val) { - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val); - intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); + intel_de_write(display, GEN8_DE_PORT_IMR, new_val); + intel_de_posting_read(display, GEN8_DE_PORT_IMR); } } @@ -113,6 +115,7 @@ static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, enum pipe pipe, u32 interrupt_mask, u32 enabled_irq_mask) { + struct intel_display *display = &dev_priv->display; u32 new_val; lockdep_assert_held(&dev_priv->irq_lock); @@ -128,9 +131,8 @@ static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, if (new_val != dev_priv->display.irq.de_irq_mask[pipe]) { dev_priv->display.irq.de_irq_mask[pipe] = new_val; - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), - dev_priv->display.irq.de_irq_mask[pipe]); - intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); + intel_de_write(display, GEN8_DE_PIPE_IMR(pipe), display->irq.de_irq_mask[pipe]); + intel_de_posting_read(display, GEN8_DE_PIPE_IMR(pipe)); } } @@ -156,7 +158,8 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, u32 interrupt_mask, u32 enabled_irq_mask) { - u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR); + struct intel_display *display = &dev_priv->display; + u32 sdeimr = intel_de_read(display, SDEIMR); sdeimr &= ~interrupt_mask; sdeimr |= (~enabled_irq_mask & interrupt_mask); @@ -168,8 +171,8 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) return; - intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr); - intel_uncore_posting_read(&dev_priv->uncore, SDEIMR); + intel_de_write(display, SDEIMR, sdeimr); + intel_de_posting_read(display, SDEIMR); } void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits) @@ -229,6 +232,7 @@ out: void i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask) { + struct intel_display *display = &dev_priv->display; i915_reg_t reg = PIPESTAT(dev_priv, pipe); u32 enable_mask; @@ -245,13 +249,14 @@ void i915_enable_pipestat(struct drm_i915_private *dev_priv, dev_priv->display.irq.pipestat_irq_mask[pipe] |= status_mask; enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); - intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); - intel_uncore_posting_read(&dev_priv->uncore, reg); + intel_de_write(display, reg, enable_mask | status_mask); + intel_de_posting_read(display, reg); } void i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask) { + struct intel_display *display = &dev_priv->display; i915_reg_t reg = PIPESTAT(dev_priv, pipe); u32 enable_mask; @@ -268,8 +273,8 @@ void i915_disable_pipestat(struct drm_i915_private *dev_priv, dev_priv->display.irq.pipestat_irq_mask[pipe] &= ~status_mask; enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); - intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); - intel_uncore_posting_read(&dev_priv->uncore, reg); + intel_de_write(display, reg, enable_mask | status_mask); + intel_de_posting_read(display, reg); } static bool i915_has_legacy_blc_interrupt(struct intel_display *display) @@ -373,55 +378,58 @@ static void flip_done_handler(struct drm_i915_private *i915, static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_display *display = &dev_priv->display; + display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_HSW(pipe)), + intel_de_read(display, PIPE_CRC_RES_HSW(pipe)), 0, 0, 0, 0); } static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_display *display = &dev_priv->display; + display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe))); + intel_de_read(display, PIPE_CRC_RES_1_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_2_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_3_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_4_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_5_IVB(pipe))); } static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_display *display = &dev_priv->display; u32 res1, res2; if (DISPLAY_VER(dev_priv) >= 3) - res1 = intel_uncore_read(&dev_priv->uncore, - PIPE_CRC_RES_RES1_I915(dev_priv, pipe)); + res1 = intel_de_read(display, PIPE_CRC_RES_RES1_I915(dev_priv, pipe)); else res1 = 0; if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) - res2 = intel_uncore_read(&dev_priv->uncore, - PIPE_CRC_RES_RES2_G4X(dev_priv, pipe)); + res2 = intel_de_read(display, PIPE_CRC_RES_RES2_G4X(dev_priv, pipe)); else res2 = 0; display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(dev_priv, pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(dev_priv, pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(dev_priv, pipe)), + intel_de_read(display, PIPE_CRC_RES_RED(dev_priv, pipe)), + intel_de_read(display, PIPE_CRC_RES_GREEN(dev_priv, pipe)), + intel_de_read(display, PIPE_CRC_RES_BLUE(dev_priv, pipe)), res1, res2); } static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; enum pipe pipe; for_each_pipe(dev_priv, pipe) { - intel_uncore_write(&dev_priv->uncore, - PIPESTAT(dev_priv, pipe), - PIPESTAT_INT_STATUS_MASK | - PIPE_FIFO_UNDERRUN_STATUS); + intel_de_write(display, + PIPESTAT(dev_priv, pipe), + PIPESTAT_INT_STATUS_MASK | PIPE_FIFO_UNDERRUN_STATUS); dev_priv->display.irq.pipestat_irq_mask[pipe] = 0; } @@ -430,6 +438,7 @@ static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, u32 iir, u32 pipe_stats[I915_MAX_PIPES]) { + struct intel_display *display = &dev_priv->display; enum pipe pipe; spin_lock(&dev_priv->irq_lock); @@ -474,7 +483,7 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, continue; reg = PIPESTAT(dev_priv, pipe); - pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; + pipe_stats[pipe] = intel_de_read(display, reg) & status_mask; enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); /* @@ -487,8 +496,8 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, * an interrupt is still pending. */ if (pipe_stats[pipe]) { - intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]); - intel_uncore_write(&dev_priv->uncore, reg, enable_mask); + intel_de_write(display, reg, pipe_stats[pipe]); + intel_de_write(display, reg, enable_mask); } } spin_unlock(&dev_priv->irq_lock); @@ -605,7 +614,7 @@ static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) for_each_pipe(dev_priv, pipe) drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), - intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); + intel_de_read(display, FDI_RX_IIR(pipe))); } if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) @@ -624,7 +633,8 @@ static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) static void ivb_err_int_handler(struct drm_i915_private *dev_priv) { - u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT); + struct intel_display *display = &dev_priv->display; + u32 err_int = intel_de_read(display, GEN7_ERR_INT); enum pipe pipe; if (err_int & ERR_INT_POISON) @@ -642,12 +652,13 @@ static void ivb_err_int_handler(struct drm_i915_private *dev_priv) } } - intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int); + intel_de_write(display, GEN7_ERR_INT, err_int); } static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) { - u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT); + struct intel_display *display = &dev_priv->display; + u32 serr_int = intel_de_read(display, SERR_INT); enum pipe pipe; if (serr_int & SERR_INT_POISON) @@ -657,7 +668,7 @@ static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); - intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int); + intel_de_write(display, SERR_INT, serr_int); } static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) @@ -691,7 +702,7 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) for_each_pipe(dev_priv, pipe) drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), - intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); + intel_de_read(display, FDI_RX_IIR(pipe))); } if (pch_iir & SDE_ERROR_CPT) @@ -732,7 +743,7 @@ void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) /* check event from PCH */ if (de_iir & DE_PCH_EVENT) { - u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); + u32 pch_iir = intel_de_read(display, SDEIIR); if (HAS_PCH_CPT(dev_priv)) cpt_irq_handler(dev_priv, pch_iir); @@ -740,7 +751,7 @@ void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) ibx_irq_handler(dev_priv, pch_iir); /* should clear PCH hotplug event before clear CPU irq */ - intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); + intel_de_write(display, SDEIIR, pch_iir); } if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT) @@ -766,8 +777,7 @@ void ivb_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) struct intel_dp *intel_dp = enc_to_intel_dp(encoder); u32 psr_iir; - psr_iir = intel_uncore_rmw(&dev_priv->uncore, - EDP_PSR_IIR, 0, 0); + psr_iir = intel_de_rmw(display, EDP_PSR_IIR, 0, 0); intel_psr_irq_handler(intel_dp, psr_iir); break; } @@ -789,12 +799,12 @@ void ivb_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) /* check event from PCH */ if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { - u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); + u32 pch_iir = intel_de_read(display, SDEIIR); cpt_irq_handler(dev_priv, pch_iir); /* clear PCH hotplug event before clear CPU irq */ - intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); + intel_de_write(display, SDEIIR, pch_iir); } } @@ -925,8 +935,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) } if (iir & XELPDP_RM_TIMEOUT) { - u32 val = intel_uncore_read(&dev_priv->uncore, - RM_TIMEOUT_REG_CAPTURE); + u32 val = intel_de_read(display, RM_TIMEOUT_REG_CAPTURE); drm_warn(&dev_priv->drm, "Register Access Timeout = 0x%x\n", val); found = true; } @@ -949,7 +958,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) else iir_reg = EDP_PSR_IIR; - psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0); + psr_iir = intel_de_rmw(display, iir_reg, 0, 0); if (psr_iir) found = true; @@ -969,6 +978,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, u32 te_trigger) { + struct intel_display *display = &dev_priv->display; enum pipe pipe = INVALID_PIPE; enum transcoder dsi_trans; enum port port; @@ -978,8 +988,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, * Incase of dual link, TE comes from DSI_1 * this is to check if dual link is enabled */ - val = intel_uncore_read(&dev_priv->uncore, - TRANS_DDI_FUNC_CTL2(dev_priv, TRANSCODER_DSI_0)); + val = intel_de_read(display, TRANS_DDI_FUNC_CTL2(dev_priv, TRANSCODER_DSI_0)); val &= PORT_SYNC_MODE_ENABLE; /* @@ -991,7 +1000,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; /* Check if DSI configured in command mode */ - val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans)); + val = intel_de_read(display, DSI_TRANS_FUNC_CONF(dsi_trans)); val = val & OP_MODE_MASK; if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { @@ -1000,8 +1009,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, } /* Get PIPE for handling VBLANK event */ - val = intel_uncore_read(&dev_priv->uncore, - TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans)); + val = intel_de_read(display, TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans)); switch (val & TRANS_DDI_EDP_INPUT_MASK) { case TRANS_DDI_EDP_INPUT_A_ON: pipe = PIPE_A; @@ -1021,7 +1029,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, /* clear TE in dsi IIR */ port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; - intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); + intel_de_rmw(display, DSI_INTR_IDENT_REG(port), 0, 0); } static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) @@ -1034,10 +1042,11 @@ static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir) { + struct intel_display *display = &i915->display; u32 pica_ier = 0; *pica_iir = 0; - *pch_iir = intel_de_read(i915, SDEIIR); + *pch_iir = intel_de_read(display, SDEIIR); if (!*pch_iir) return; @@ -1049,15 +1058,15 @@ static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_i if (*pch_iir & SDE_PICAINTERRUPT) { drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTL); - pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0); - *pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR); - intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir); + pica_ier = intel_de_rmw(display, PICAINTERRUPT_IER, ~0, 0); + *pica_iir = intel_de_read(display, PICAINTERRUPT_IIR); + intel_de_write(display, PICAINTERRUPT_IIR, *pica_iir); } - intel_de_write(i915, SDEIIR, *pch_iir); + intel_de_write(display, SDEIIR, *pch_iir); if (pica_ier) - intel_de_write(i915, PICAINTERRUPT_IER, pica_ier); + intel_de_write(display, PICAINTERRUPT_IER, pica_ier); } void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) @@ -1069,9 +1078,9 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv)); if (master_ctl & GEN8_DE_MISC_IRQ) { - iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR); + iir = intel_de_read(display, GEN8_DE_MISC_IIR); if (iir) { - intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir); + intel_de_write(display, GEN8_DE_MISC_IIR, iir); gen8_de_misc_irq_handler(dev_priv, iir); } else { drm_err_ratelimited(&dev_priv->drm, @@ -1080,9 +1089,9 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) } if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { - iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR); + iir = intel_de_read(display, GEN11_DE_HPD_IIR); if (iir) { - intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir); + intel_de_write(display, GEN11_DE_HPD_IIR, iir); gen11_hpd_irq_handler(dev_priv, iir); } else { drm_err_ratelimited(&dev_priv->drm, @@ -1091,11 +1100,11 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) } if (master_ctl & GEN8_DE_PORT_IRQ) { - iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR); + iir = intel_de_read(display, GEN8_DE_PORT_IIR); if (iir) { bool found = false; - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir); + intel_de_write(display, GEN8_DE_PORT_IIR, iir); if (iir & gen8_de_port_aux_mask(dev_priv)) { intel_dp_aux_irq_handler(display); @@ -1148,14 +1157,14 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) continue; - iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); + iir = intel_de_read(display, GEN8_DE_PIPE_IIR(pipe)); if (!iir) { drm_err_ratelimited(&dev_priv->drm, "The master control interrupt lied (DE PIPE)!\n"); continue; } - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir); + intel_de_write(display, GEN8_DE_PIPE_IIR(pipe), iir); if (iir & GEN8_PIPE_VBLANK) intel_handle_vblank(dev_priv, pipe); @@ -1221,14 +1230,15 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl) { + struct intel_display *display = &i915->display; u32 iir; if (!(master_ctl & GEN11_GU_MISC_IRQ)) return 0; - iir = intel_de_read(i915, GEN11_GU_MISC_IIR); + iir = intel_de_read(display, GEN11_GU_MISC_IIR); if (likely(iir)) - intel_de_write(i915, GEN11_GU_MISC_IIR, iir); + intel_de_write(display, GEN11_GU_MISC_IIR, iir); return iir; } @@ -1243,6 +1253,7 @@ void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir) void gen11_display_irq_handler(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; u32 disp_ctl; disable_rpm_wakeref_asserts(&i915->runtime_pm); @@ -1250,17 +1261,18 @@ void gen11_display_irq_handler(struct drm_i915_private *i915) * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ * for the display related bits. */ - disp_ctl = intel_de_read(i915, GEN11_DISPLAY_INT_CTL); + disp_ctl = intel_de_read(display, GEN11_DISPLAY_INT_CTL); - intel_de_write(i915, GEN11_DISPLAY_INT_CTL, 0); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); gen8_de_irq_handler(i915, disp_ctl); - intel_de_write(i915, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); enable_rpm_wakeref_asserts(&i915->runtime_pm); } static void i915gm_irq_cstate_wa_enable(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; lockdep_assert_held(&i915->drm.vblank_time_lock); /* @@ -1270,15 +1282,18 @@ static void i915gm_irq_cstate_wa_enable(struct drm_i915_private *i915) * only when vblank/CRC interrupts are actually enabled. */ if (i915->display.irq.vblank_enabled++ == 0) - intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); + intel_de_write(display, SCPD0, + _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); } static void i915gm_irq_cstate_wa_disable(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; lockdep_assert_held(&i915->drm.vblank_time_lock); if (--i915->display.irq.vblank_enabled == 0) - intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); + intel_de_write(display, SCPD0, + _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); } void i915gm_irq_cstate_wa(struct drm_i915_private *i915, bool enable) @@ -1398,7 +1413,7 @@ void ilk_disable_vblank(struct drm_crtc *crtc) static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, bool enable) { - struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + struct intel_display *display = to_intel_display(intel_crtc); enum port port; if (!(intel_crtc->mode_flags & @@ -1411,10 +1426,9 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, else port = PORT_A; - intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, - enable ? 0 : DSI_TE_EVENT); + intel_de_rmw(display, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, enable ? 0 : DSI_TE_EVENT); - intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); + intel_de_rmw(display, DSI_INTR_IDENT_REG(port), 0, 0); return true; } @@ -1483,15 +1497,16 @@ void bdw_disable_vblank(struct drm_crtc *_crtc) static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; if (IS_CHERRYVIEW(dev_priv)) - intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); + intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); else - intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); + intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); - intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT(dev_priv), 0, 0); + intel_de_rmw(display, PORT_HOTPLUG_STAT(dev_priv), 0, 0); i9xx_pipestat_irq_reset(dev_priv); @@ -1507,10 +1522,11 @@ void vlv_display_irq_reset(struct drm_i915_private *dev_priv) void i9xx_display_irq_reset(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; + if (I915_HAS_HOTPLUG(i915)) { i915_hotplug_interrupt_update(i915, 0xffffffff, 0); - intel_uncore_rmw(&i915->uncore, - PORT_HOTPLUG_STAT(i915), 0, 0); + intel_de_rmw(display, PORT_HOTPLUG_STAT(i915), 0, 0); } i9xx_pipestat_irq_reset(i915); @@ -1552,14 +1568,15 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) void gen8_display_irq_reset(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; enum pipe pipe; if (!HAS_DISPLAY(dev_priv)) return; - intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); - intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); + intel_de_write(display, EDP_PSR_IMR, 0xffffffff); + intel_de_write(display, EDP_PSR_IIR, 0xffffffff); for_each_pipe(dev_priv, pipe) if (intel_display_power_is_enabled(dev_priv, @@ -1572,6 +1589,7 @@ void gen8_display_irq_reset(struct drm_i915_private *dev_priv) void gen11_display_irq_reset(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; enum pipe pipe; u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | @@ -1580,7 +1598,7 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); if (DISPLAY_VER(dev_priv) >= 12) { enum transcoder trans; @@ -1592,16 +1610,16 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv) if (!intel_display_power_is_enabled(dev_priv, domain)) continue; - intel_uncore_write(uncore, - TRANS_PSR_IMR(dev_priv, trans), - 0xffffffff); - intel_uncore_write(uncore, - TRANS_PSR_IIR(dev_priv, trans), - 0xffffffff); + intel_de_write(display, + TRANS_PSR_IMR(dev_priv, trans), + 0xffffffff); + intel_de_write(display, + TRANS_PSR_IIR(dev_priv, trans), + 0xffffffff); } } else { - intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); - intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); + intel_de_write(display, EDP_PSR_IMR, 0xffffffff); + intel_de_write(display, EDP_PSR_IIR, 0xffffffff); } for_each_pipe(dev_priv, pipe) @@ -1890,23 +1908,25 @@ static void icp_irq_postinstall(struct drm_i915_private *dev_priv) void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; + if (!HAS_DISPLAY(dev_priv)) return; gen8_de_irq_postinstall(dev_priv); - intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, - GEN11_DISPLAY_IRQ_ENABLE); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); } void dg1_de_irq_postinstall(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; + if (!HAS_DISPLAY(i915)) return; gen8_de_irq_postinstall(i915); - intel_uncore_write(&i915->uncore, GEN11_DISPLAY_INT_CTL, - GEN11_DISPLAY_IRQ_ENABLE); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); } void intel_display_irq_init(struct drm_i915_private *i915) -- cgit v1.2.3-59-g8ed1b From 6d531e350572163f5e3ec832710d459d1232c3cb Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Mon, 13 Jan 2025 17:38:57 -0300 Subject: drm/i915/display: Wrap IRQ-specific uncore functions The current display IRQ code calls some IRQ-specific helpers that use intel_uncore_*() MMIO functions instead of the display-specific ones. Wrap those helpers to ensure that the proper display-specific hooks (currently only DMC wakelock handling) are called. v2: - Move functions to intel_display_irq.c instead of having them in intel_de.h. (Jani) Cc: Jani Nikula Reviewed-by: Luca Coelho Signed-off-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20250113204306.112266-3-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/display/intel_display_irq.c | 128 +++++++++++++++-------- 1 file changed, 83 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 9662368a651d..d9734fcd0d45 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -15,6 +15,7 @@ #include "intel_display_irq.h" #include "intel_display_trace.h" #include "intel_display_types.h" +#include "intel_dmc_wl.h" #include "intel_dp_aux.h" #include "intel_dsb.h" #include "intel_fdi_regs.h" @@ -25,6 +26,46 @@ #include "intel_pmdemand.h" #include "intel_psr.h" #include "intel_psr_regs.h" +#include "intel_uncore.h" + +static void +intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs regs, + u32 imr_val, u32 ier_val) +{ + intel_dmc_wl_get(display, regs.imr); + intel_dmc_wl_get(display, regs.ier); + intel_dmc_wl_get(display, regs.iir); + + gen2_irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); + + intel_dmc_wl_put(display, regs.iir); + intel_dmc_wl_put(display, regs.ier); + intel_dmc_wl_put(display, regs.imr); +} + +static void +intel_display_irq_regs_reset(struct intel_display *display, struct i915_irq_regs regs) +{ + intel_dmc_wl_get(display, regs.imr); + intel_dmc_wl_get(display, regs.ier); + intel_dmc_wl_get(display, regs.iir); + + gen2_irq_reset(to_intel_uncore(display->drm), regs); + + intel_dmc_wl_put(display, regs.iir); + intel_dmc_wl_put(display, regs.ier); + intel_dmc_wl_put(display, regs.imr); +} + +static void +intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_reg_t reg) +{ + intel_dmc_wl_get(display, reg); + + gen2_assert_iir_is_zero(to_intel_uncore(display->drm), reg); + + intel_dmc_wl_put(display, reg); +} static void intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) @@ -1498,7 +1539,6 @@ void bdw_disable_vblank(struct drm_crtc *_crtc) static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv) { struct intel_display *display = &dev_priv->display; - struct intel_uncore *uncore = &dev_priv->uncore; if (IS_CHERRYVIEW(dev_priv)) intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); @@ -1510,7 +1550,7 @@ static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); - gen2_irq_reset(uncore, VLV_IRQ_REGS); + intel_display_irq_regs_reset(display, VLV_IRQ_REGS); dev_priv->irq_mask = ~0u; } @@ -1534,8 +1574,7 @@ void i9xx_display_irq_reset(struct drm_i915_private *i915) void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; - + struct intel_display *display = &dev_priv->display; u32 pipestat_mask; u32 enable_mask; enum pipe pipe; @@ -1563,13 +1602,12 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->irq_mask = ~enable_mask; - gen2_irq_init(uncore, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask); + intel_display_irq_regs_init(display, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask); } void gen8_display_irq_reset(struct drm_i915_private *dev_priv) { struct intel_display *display = &dev_priv->display; - struct intel_uncore *uncore = &dev_priv->uncore; enum pipe pipe; if (!HAS_DISPLAY(dev_priv)) @@ -1581,16 +1619,15 @@ void gen8_display_irq_reset(struct drm_i915_private *dev_priv) for_each_pipe(dev_priv, pipe) if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) - gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe)); + intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - gen2_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS); - gen2_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); } void gen11_display_irq_reset(struct drm_i915_private *dev_priv) { struct intel_display *display = &dev_priv->display; - struct intel_uncore *uncore = &dev_priv->uncore; enum pipe pipe; u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D); @@ -1625,24 +1662,24 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv) for_each_pipe(dev_priv, pipe) if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) - gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe)); + intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - gen2_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS); - gen2_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); if (DISPLAY_VER(dev_priv) >= 14) - gen2_irq_reset(uncore, PICAINTERRUPT_IRQ_REGS); + intel_display_irq_regs_reset(display, PICAINTERRUPT_IRQ_REGS); else - gen2_irq_reset(uncore, GEN11_DE_HPD_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN11_DE_HPD_IRQ_REGS); if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - gen2_irq_reset(uncore, SDE_IRQ_REGS); + intel_display_irq_regs_reset(display, SDE_IRQ_REGS); } void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u8 pipe_mask) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | gen8_de_pipe_flip_done_mask(dev_priv); enum pipe pipe; @@ -1655,9 +1692,9 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, } for_each_pipe_masked(dev_priv, pipe, pipe_mask) - gen2_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe), - dev_priv->display.irq.de_irq_mask[pipe], - ~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier); + intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + dev_priv->display.irq.de_irq_mask[pipe], + ~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier); spin_unlock_irq(&dev_priv->irq_lock); } @@ -1665,7 +1702,7 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, u8 pipe_mask) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; enum pipe pipe; spin_lock_irq(&dev_priv->irq_lock); @@ -1676,7 +1713,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, } for_each_pipe_masked(dev_priv, pipe, pipe_mask) - gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe)); + intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); spin_unlock_irq(&dev_priv->irq_lock); @@ -1697,7 +1734,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, */ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; u32 mask; if (HAS_PCH_NOP(dev_priv)) @@ -1710,7 +1747,7 @@ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) else mask = SDE_GMBUS_CPT; - gen2_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff); + intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) @@ -1743,7 +1780,7 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) void ilk_de_irq_postinstall(struct drm_i915_private *i915) { - struct intel_uncore *uncore = &i915->uncore; + struct intel_display *display = &i915->display; u32 display_mask, extra_mask; if (DISPLAY_VER(i915) >= 7) { @@ -1767,7 +1804,7 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915) } if (IS_HASWELL(i915)) { - gen2_assert_iir_is_zero(uncore, EDP_PSR_IIR); + intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); display_mask |= DE_EDP_PSR_INT_HSW; } @@ -1778,8 +1815,8 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915) ibx_irq_postinstall(i915); - gen2_irq_init(uncore, DE_IRQ_REGS, i915->irq_mask, - display_mask | extra_mask); + intel_display_irq_regs_init(display, DE_IRQ_REGS, i915->irq_mask, + display_mask | extra_mask); } static void mtp_irq_postinstall(struct drm_i915_private *i915); @@ -1788,7 +1825,6 @@ static void icp_irq_postinstall(struct drm_i915_private *i915); void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) { struct intel_display *display = &dev_priv->display; - struct intel_uncore *uncore = &dev_priv->uncore; u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) | GEN8_PIPE_CDCLK_CRC_DONE; @@ -1854,11 +1890,11 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) if (!intel_display_power_is_enabled(dev_priv, domain)) continue; - gen2_assert_iir_is_zero(uncore, - TRANS_PSR_IIR(dev_priv, trans)); + intel_display_irq_regs_assert_irr_is_zero(display, + TRANS_PSR_IIR(dev_priv, trans)); } } else { - gen2_assert_iir_is_zero(uncore, EDP_PSR_IIR); + intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); } for_each_pipe(dev_priv, pipe) { @@ -1866,44 +1902,46 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) - gen2_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe), - dev_priv->display.irq.de_irq_mask[pipe], - de_pipe_enables); + intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + dev_priv->display.irq.de_irq_mask[pipe], + de_pipe_enables); } - gen2_irq_init(uncore, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables); - gen2_irq_init(uncore, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked); + intel_display_irq_regs_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, + de_port_enables); + intel_display_irq_regs_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, + de_misc_masked); if (IS_DISPLAY_VER(dev_priv, 11, 13)) { u32 de_hpd_masked = 0; u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; - gen2_irq_init(uncore, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, - de_hpd_enables); + intel_display_irq_regs_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, + de_hpd_enables); } } static void mtp_irq_postinstall(struct drm_i915_private *i915) { - struct intel_uncore *uncore = &i915->uncore; + struct intel_display *display = &i915->display; u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT; u32 de_hpd_mask = XELPDP_AUX_TC_MASK; u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK; - gen2_irq_init(uncore, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, - de_hpd_enables); + intel_display_irq_regs_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, + de_hpd_enables); - gen2_irq_init(uncore, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); + intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); } static void icp_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; u32 mask = SDE_GMBUS_ICP; - gen2_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff); + intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) -- cgit v1.2.3-59-g8ed1b From 9983fd3c8dc315e0e4869d4522787163de57e0e9 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Mon, 13 Jan 2025 17:38:58 -0300 Subject: drm/i915/dmc_wl: Track pipe interrupt registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pipe interrupt registers live in their respective pipes' power wells, which are below PG0. That means that they must also be tracked as registers that are powered-off during dynamic DC states. There are probably more ranges that we need to track down and add to the powered_off_ranges. However, let's make this change only about pipe interrupt registers to fix some vblank timeouts observed due to the DMC wakelock not being taken for those registers. In the future, we might want to replace powered_off_ranges with a new table to represent registers in PG0, which should be probably easier to maintain. Any register not belonging to that table should be considered powered off during dynamic DC states and, as such, requiring the DMC wakelock for access. Bspec: 72519, 71583 Reviewed-by: Jouni Högander Signed-off-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20250113204306.112266-4-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 1bdc08e6aa45..43884740f8ea 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -67,6 +67,7 @@ struct intel_dmc_wl_range { }; static const struct intel_dmc_wl_range powered_off_ranges[] = { + { .start = 0x44400, .end = 0x4447f }, /* PIPE interrupt registers */ { .start = 0x60000, .end = 0x7ffff }, {}, }; -- cgit v1.2.3-59-g8ed1b From 474c4dd29f666145dee7b5dce56d024a26e9550c Mon Sep 17 00:00:00 2001 From: Francois Dugast Date: Thu, 16 Jan 2025 13:45:32 +0100 Subject: drm/xe: Add missing SPDX license identifiers Ensure all Xe driver files have a proper SPDX license identifier, add it in files where it was missing. Link: https://patchwork.freedesktop.org/patch/msgid/20250116124532.1480351-1-francois.dugast@intel.com Signed-off-by: Francois Dugast Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/xe/Kconfig.profile | 1 + drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Kconfig.profile b/drivers/gpu/drm/xe/Kconfig.profile index ba17a25e8db3..7530df998148 100644 --- a/drivers/gpu/drm/xe/Kconfig.profile +++ b/drivers/gpu/drm/xe/Kconfig.profile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only config DRM_XE_JOB_TIMEOUT_MAX int "Default max job timeout (ms)" default 10000 # milliseconds diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h index 9c4cf050059a..41d39d67817a 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + #ifndef _I915_GEM_STOLEN_H_ #define _I915_GEM_STOLEN_H_ -- cgit v1.2.3-59-g8ed1b From 931a765c2d95c46cb818eccc641006c86697486f Mon Sep 17 00:00:00 2001 From: Youssef Samir Date: Fri, 13 Dec 2024 11:51:10 -0700 Subject: accel/qaic: Change aic100_image_table definition aic100_image_table is currently defined as a "const char *" array, this can potentially lead to the accidental modification of the pointers inside. Also, checkpatch.pl gives a warning about it. Change the type to a "const char * const" array to make the pointers immutable, preventing accidental modification of the images' paths. Signed-off-by: Youssef Samir Reviewed-by: Carl Vanderlip Reviewed-by: Jeffrey Hugo Signed-off-by: Jeffrey Hugo Reviewed-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20241213185110.2469159-1-quic_jhugo@quicinc.com --- drivers/accel/qaic/sahara.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/qaic/sahara.c b/drivers/accel/qaic/sahara.c index 21d58aed0deb..09c8b055aa81 100644 --- a/drivers/accel/qaic/sahara.c +++ b/drivers/accel/qaic/sahara.c @@ -160,7 +160,7 @@ struct sahara_context { struct work_struct fw_work; struct work_struct dump_work; struct mhi_device *mhi_dev; - const char **image_table; + const char * const *image_table; u32 table_size; u32 active_image_id; const struct firmware *firmware; @@ -177,7 +177,7 @@ struct sahara_context { bool is_mem_dump_mode; }; -static const char *aic100_image_table[] = { +static const char * const aic100_image_table[] = { [1] = "qcom/aic100/fw1.bin", [2] = "qcom/aic100/fw2.bin", [4] = "qcom/aic100/fw4.bin", -- cgit v1.2.3-59-g8ed1b From c03dd019f0b56c40f42fa0e7785eaa109e0bdcd6 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 17 Jan 2025 09:00:29 +0800 Subject: drm/panel-edp: Add BOE NV140FHM-NZ panel entry Add an eDP panel entry for BOE NV140FHM-NZ. No datasheet found for this panel, so the timing is based on a similar NV140FHM-N41 datasheet that I can find on internet[0]. edid: 00 ff ff ff ff ff ff 00 09 e5 09 0b 00 00 00 00 01 20 01 04 a5 1f 11 78 03 9b 75 99 5b 5d 8f 2a 23 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 c8 37 80 cc 70 38 28 40 6c 30 aa 00 35 ae 10 00 00 1a 00 00 00 fd 00 30 3c 43 43 8f 01 0a 20 20 20 20 20 20 00 00 00 fe 00 42 4f 45 20 48 46 0a 20 20 20 20 20 20 00 00 00 fe 00 4e 56 31 34 30 46 48 4d 2d 4e 34 5a 0a 00 35 [0]:http://www.tfinno.com/PIC/PIC/20215121628440.pdf Signed-off-by: Andy Yan Reviewed-by: Thomas Zimmermann Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250117010039.1815430-1-andyshrk@163.com --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 319ebc184c16..1721a3397dbf 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1915,6 +1915,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('B', 'O', 'E', 0x0ac5, &delay_200_500_e50, "NV116WHM-N4C"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ae8, &delay_200_500_e50_p2e80, "NV140WUM-N41"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b09, &delay_200_500_e50_po2e200, "NV140FHM-NZ"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b34, &delay_200_500_e80, "NV122WUM-N41"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b43, &delay_200_500_e200, "NV140FHM-T09"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b56, &delay_200_500_e80, "NT140FHM-N47"), -- cgit v1.2.3-59-g8ed1b From 709631924ee544ba0b661c41b442427897569f30 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 20 Dec 2024 17:43:29 -0800 Subject: drm/i915/uc: Include requested frequency in slow firmware load messages To aid debug of sporadic issues, include the requested frequency in the debug message as well as the actual frequency. That way we know for certain that the clamping is not because the driver forgot to ask. Signed-off-by: John Harrison Reviewed-by: Vinay Belgaumkar Reviewed-by: Krzysztof Karas Link: https://patchwork.freedesktop.org/patch/msgid/20241221014329.4048408-1-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 11 ++++++----- drivers/gpu/drm/i915/gt/uc/intel_huc.c | 12 +++++++----- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 23f54c84cbab..e37d227dc199 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -259,13 +259,14 @@ static int guc_wait_ucode(struct intel_guc *guc) } else if (delta_ms > 200) { guc_warn(guc, "excessive init time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", delta_ms, status, count, ret); - guc_warn(guc, "excessive init time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", - intel_rps_read_actual_frequency(>->rps), before_freq, + guc_warn(guc, "excessive init time: [freq = %dMHz -> %dMHz vs %dMHz, perf_limit_reasons = 0x%08X]\n", + before_freq, intel_rps_read_actual_frequency(>->rps), + intel_rps_get_requested_frequency(>->rps), intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); } else { - guc_dbg(guc, "init took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", - delta_ms, intel_rps_read_actual_frequency(>->rps), - before_freq, status, count, ret); + guc_dbg(guc, "init took %lldms, freq = %dMHz -> %dMHz vs %dMHz, status = 0x%08X, count = %d, ret = %d\n", + delta_ms, before_freq, intel_rps_read_actual_frequency(>->rps), + intel_rps_get_requested_frequency(>->rps), status, count, ret); } return ret; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index 80a09df20355..089a86df33a9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -489,13 +489,15 @@ int intel_huc_wait_for_auth_complete(struct intel_huc *huc, if (delta_ms > 50) { huc_warn(huc, "excessive auth time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", delta_ms, huc->status[type].reg.reg, count, ret); - huc_warn(huc, "excessive auth time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", - intel_rps_read_actual_frequency(>->rps), before_freq, + huc_warn(huc, "excessive auth time: [freq = %dMHz -> %dMHz vs %dMHz, perf_limit_reasons = 0x%08X]\n", + before_freq, intel_rps_read_actual_frequency(>->rps), + intel_rps_get_requested_frequency(>->rps), intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); } else { - huc_dbg(huc, "auth took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", - delta_ms, intel_rps_read_actual_frequency(>->rps), - before_freq, huc->status[type].reg.reg, count, ret); + huc_dbg(huc, "auth took %lldms, freq = %dMHz -> %dMHz vs %dMHz, status = 0x%08X, count = %d, ret = %d\n", + delta_ms, before_freq, intel_rps_read_actual_frequency(>->rps), + intel_rps_get_requested_frequency(>->rps), + huc->status[type].reg.reg, count, ret); } /* mark the load process as complete even if the wait failed */ -- cgit v1.2.3-59-g8ed1b From bbd8429264baf8bc3c40cefda048560ae0eb7890 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 14 Nov 2024 18:59:54 +0100 Subject: drm/xe: Always setup GT MMIO adjustment data While we believed that xe_gt_mmio_init() will be called just once per GT, this might not be a case due to some tweaks that need to performed by the VF driver during early probe. To avoid leaving any stale data in case of the re-run, reset the GT MMIO adjustment data for the non-media GT case. Signed-off-by: Michal Wajdeczko Cc: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20241114175955.2299-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 26e64530ada2..b5c313a3e946 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -643,6 +643,9 @@ void xe_gt_mmio_init(struct xe_gt *gt) if (gt->info.type == XE_GT_TYPE_MEDIA) { gt->mmio.adj_offset = MEDIA_GT_GSI_OFFSET; gt->mmio.adj_limit = MEDIA_GT_GSI_LENGTH; + } else { + gt->mmio.adj_offset = 0; + gt->mmio.adj_limit = 0; } if (IS_SRIOV_VF(gt_to_xe(gt))) -- cgit v1.2.3-59-g8ed1b From 13265fe7426ec9ba5aa86baab913417ca361e8a4 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 14 Jan 2025 22:13:47 +0100 Subject: drm/xe/vf: Perform early GT MMIO initialization to read GMDID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VFs need to communicate with the GuC to obtain the GMDID value and existing GuC functions used for that assume that the GT has it's MMIO members already setup. However, due to recent refactoring the gt->mmio is initialized later, and any attempt by the VF to use xe_mmio_read|write() from GuC functions will lead to NPD crash due to unset MMIO register address: [] xe 0000:00:02.1: [drm] Running in SR-IOV VF mode [] xe 0000:00:02.1: [drm] GT0: sending H2G MMIO 0x5507 [] BUG: unable to handle page fault for address: 0000000000190240 Since we are already tweaking the id and type of the primary GT to mimic it's a Media GT before initializing the GuC communication, we can also call xe_gt_mmio_init() to perform early setup of the gt->mmio which will make those GuC functions work again. Signed-off-by: Michal Wajdeczko Cc: Matt Roper Cc: Piotr Piórkowski Reviewed-by: Piotr Piórkowski Link: https://patchwork.freedesktop.org/patch/msgid/20250114211347.1083-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 48d1c81d441e..bf35a18bf5e7 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -501,6 +501,7 @@ static void read_gmdid(struct xe_device *xe, enum xe_gmdid_type type, u32 *ver, gt->info.type = XE_GT_TYPE_MAIN; } + xe_gt_mmio_init(gt); xe_guc_comm_init_early(>->uc.guc); /* Don't bother with GMDID if failed to negotiate the GuC ABI */ -- cgit v1.2.3-59-g8ed1b From 9cd3f4efc870463f17f6c29114c61fb6bfcaa291 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:41:54 +0100 Subject: drm/xe/sa: Always call drm_suballoc_manager_fini() After successful call to drm_suballoc_manager_init() we should make sure to call drm_suballoc_manager_fini() as it may include some cleanup code even if we didn't start using it for real. As we can abort init() early due to kvzalloc() failure, we should either explicitly call drm_suballoc_manager_fini() or, even better, postpone drm_suballoc_manager_init() once we finish all other preparation steps, so we can rely on fini() that will do cleanup. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_sa.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index e055bed7ae55..4e7aba445ebc 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -57,8 +57,6 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 } sa_manager->bo = bo; sa_manager->is_iomem = bo->vmap.is_iomem; - - drm_suballoc_manager_init(&sa_manager->base, managed_size, align); sa_manager->gpu_addr = xe_bo_ggtt_addr(bo); if (bo->vmap.is_iomem) { @@ -72,6 +70,7 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size); } + drm_suballoc_manager_init(&sa_manager->base, managed_size, align); ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini, sa_manager); if (ret) -- cgit v1.2.3-59-g8ed1b From d29cddd49bed2c880e7c17724bcf3604e865c23a Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:41:55 +0100 Subject: drm/xe/sa: Drop redundant NULL assignments The sa_manager is drmm_kzalloc'ed so all members are already zero. And in case of kvzalloc() failure we are not returning pointer to the sa_manager at all, so no point in resetting .bo member. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_sa.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index 4e7aba445ebc..eb314ca75355 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -44,8 +44,6 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 if (!sa_manager) return ERR_PTR(-ENOMEM); - sa_manager->bo = NULL; - bo = xe_managed_bo_create_pin_map(xe, tile, size, XE_BO_FLAG_VRAM_IF_DGFX(tile) | XE_BO_FLAG_GGTT | @@ -61,10 +59,8 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 if (bo->vmap.is_iomem) { sa_manager->cpu_ptr = kvzalloc(managed_size, GFP_KERNEL); - if (!sa_manager->cpu_ptr) { - sa_manager->bo = NULL; + if (!sa_manager->cpu_ptr) return ERR_PTR(-ENOMEM); - } } else { sa_manager->cpu_ptr = bo->vmap.vaddr; memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size); -- cgit v1.2.3-59-g8ed1b From 97ee0e351f6ebbcb2a2dccdff726f75f728fede8 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:41:56 +0100 Subject: drm/xe/sa: Improve error message on init failure Instead of raw errno value we can print friendly error code and also print size of the buffer object that we fail to prepare. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_sa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index eb314ca75355..0b87599759d7 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -49,8 +49,8 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 XE_BO_FLAG_GGTT | XE_BO_FLAG_GGTT_INVALIDATE); if (IS_ERR(bo)) { - drm_err(&xe->drm, "failed to allocate bo for sa manager: %ld\n", - PTR_ERR(bo)); + drm_err(&xe->drm, "Failed to prepare %uKiB BO for SA manager (%pe)\n", + size / SZ_1K, bo); return ERR_CAST(bo); } sa_manager->bo = bo; -- cgit v1.2.3-59-g8ed1b From 7e937cdf18164ea276ce0f4bbc5755e0031280e0 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:41:57 +0100 Subject: drm/xe/sa: Tidy up coding style in init() There is no need to use tile_to_xe() since we already got the xe. And we should keep all variable declarations together, no need for separate sa_manager declaration. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-5-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_sa.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index 0b87599759d7..0e78ae46667e 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -34,13 +34,12 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align) { struct xe_device *xe = tile_to_xe(tile); + struct xe_sa_manager *sa_manager; u32 managed_size = size - SZ_4K; struct xe_bo *bo; int ret; - struct xe_sa_manager *sa_manager = drmm_kzalloc(&tile_to_xe(tile)->drm, - sizeof(*sa_manager), - GFP_KERNEL); + sa_manager = drmm_kzalloc(&xe->drm, sizeof(*sa_manager), GFP_KERNEL); if (!sa_manager) return ERR_PTR(-ENOMEM); -- cgit v1.2.3-59-g8ed1b From 0e1871f61e71d7611196b04d1b133f18fef666dd Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:41:58 +0100 Subject: drm/xe/sa: Allow making suballocations using custom gfp flags Actual xe_sa_manager implementation uses hardcoded GFP_KERNEL flag during creation of suballocations but in upcoming patch we want to reuse the xe_sa_manager in places where GFP_KERNEL is not allowed. Add another variant of the xe_sa_bo_new() function that accepts arbitrary gfp flags. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-6-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_sa.c | 15 ++++++++++++--- drivers/gpu/drm/xe/xe_sa.h | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index 0e78ae46667e..5f89e32b0640 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -74,8 +74,17 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 return sa_manager; } -struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, - unsigned int size) +/** + * __xe_sa_bo_new() - Make a suballocation but use custom gfp flags. + * @sa_manager: the &xe_sa_manager + * @size: number of bytes we want to suballocate + * @gfp: gfp flags used for memory allocation. Typically GFP_KERNEL. + * + * Try to make a suballocation of size @size. + * + * Return: a &drm_suballoc, or an ERR_PTR. + */ +struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp) { /* * BB to large, return -ENOBUFS indicating user should split @@ -84,7 +93,7 @@ struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, if (size > sa_manager->base.size) return ERR_PTR(-ENOBUFS); - return drm_suballoc_new(&sa_manager->base, size, GFP_KERNEL, true, 0); + return drm_suballoc_new(&sa_manager->base, size, gfp, true, 0); } void xe_sa_bo_flush_write(struct drm_suballoc *sa_bo) diff --git a/drivers/gpu/drm/xe/xe_sa.h b/drivers/gpu/drm/xe/xe_sa.h index 4e96483057d7..a0341eafbe77 100644 --- a/drivers/gpu/drm/xe/xe_sa.h +++ b/drivers/gpu/drm/xe/xe_sa.h @@ -5,6 +5,7 @@ #ifndef _XE_SA_H_ #define _XE_SA_H_ +#include #include "xe_sa_types.h" struct dma_fence; @@ -13,8 +14,22 @@ struct xe_tile; struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align); -struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, - u32 size); +struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp); + +/** + * xe_sa_bo_new() - Make a suballocation. + * @sa_manager: the &xe_sa_manager + * @size: number of bytes we want to suballocate + * + * Try to make a suballocation of size @size. + * + * Return: a &drm_suballoc, or an ERR_PTR. + */ +static inline struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size) +{ + return __xe_sa_bo_new(sa_manager, size, GFP_KERNEL); +} + void xe_sa_bo_flush_write(struct drm_suballoc *sa_bo); void xe_sa_bo_free(struct drm_suballoc *sa_bo, struct dma_fence *fence); -- cgit v1.2.3-59-g8ed1b From ae8b507fb8bbea2aa30783184d5728b14ce40c8f Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:41:59 +0100 Subject: drm/xe/sa: Allow creating suballocator with custom guard size Actual xe_sa_manager implementation uses hardcoded 4K to exclude it from making suballocations but in upcoming patch we want to reuse the xe_sa_manager where such 4K guard is not needed. Add another variant of the xe_sa_bo_manager_init() function that accepts arbitrary guard size. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-7-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_sa.c | 18 ++++++++++++++++-- drivers/gpu/drm/xe/xe_sa.h | 9 +++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index 5f89e32b0640..f8fe61e25518 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -31,14 +31,28 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) sa_manager->bo = NULL; } -struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align) +/** + * __xe_sa_bo_manager_init() - Create and initialize the suballocator + * @tile: the &xe_tile where allocate + * @size: number of bytes to allocate + * @guard: number of bytes to exclude from suballocations + * @align: alignment for each suballocated chunk + * + * Prepares the suballocation manager for suballocations. + * + * Return: a pointer to the &xe_sa_manager or an ERR_PTR on failure. + */ +struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align) { struct xe_device *xe = tile_to_xe(tile); struct xe_sa_manager *sa_manager; - u32 managed_size = size - SZ_4K; + u32 managed_size; struct xe_bo *bo; int ret; + xe_tile_assert(tile, size > guard); + managed_size = size - guard; + sa_manager = drmm_kzalloc(&xe->drm, sizeof(*sa_manager), GFP_KERNEL); if (!sa_manager) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/xe/xe_sa.h b/drivers/gpu/drm/xe/xe_sa.h index a0341eafbe77..de0330eb36d4 100644 --- a/drivers/gpu/drm/xe/xe_sa.h +++ b/drivers/gpu/drm/xe/xe_sa.h @@ -5,6 +5,7 @@ #ifndef _XE_SA_H_ #define _XE_SA_H_ +#include #include #include "xe_sa_types.h" @@ -12,10 +13,14 @@ struct dma_fence; struct xe_bo; struct xe_tile; -struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align); - +struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align); struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp); +static inline struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align) +{ + return __xe_sa_bo_manager_init(tile, size, SZ_4K, align); +} + /** * xe_sa_bo_new() - Make a suballocation. * @sa_manager: the &xe_sa_manager -- cgit v1.2.3-59-g8ed1b From c49ca671818a325f2221f0bda8af96e339272a5e Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:42:00 +0100 Subject: drm/xe/sa: Minor header cleanups Drop unused struct xe_bo forward declaration and, while around, fix unnecessary line split in xe_sa_bo_free() declaration. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-8-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_sa.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sa.h b/drivers/gpu/drm/xe/xe_sa.h index de0330eb36d4..1170ee5a81a8 100644 --- a/drivers/gpu/drm/xe/xe_sa.h +++ b/drivers/gpu/drm/xe/xe_sa.h @@ -10,7 +10,6 @@ #include "xe_sa_types.h" struct dma_fence; -struct xe_bo; struct xe_tile; struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align); @@ -36,8 +35,7 @@ static inline struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager } void xe_sa_bo_flush_write(struct drm_suballoc *sa_bo); -void xe_sa_bo_free(struct drm_suballoc *sa_bo, - struct dma_fence *fence); +void xe_sa_bo_free(struct drm_suballoc *sa_bo, struct dma_fence *fence); static inline struct xe_sa_manager * to_xe_sa_manager(struct drm_suballoc_manager *mng) -- cgit v1.2.3-59-g8ed1b From 696bfdf273eab9ce3dd2ff51d26ca30f7924a4bb Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:42:01 +0100 Subject: drm/xe/guc: Introduce the GuC Buffer Cache The purpose of the GuC Buffer Cache is to maintain a set ofreusable buffers that could be used while sending some of the CTB H2G actions that require separate buffer with indirect data. Currently only few PF actions need this so initialize it only when running as a PF. Signed-off-by: Michal Wajdeczko Cc: Matthew Brost Cc: Rodrigo Vivi Acked-by: Rodrigo Vivi Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-9-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_guc.c | 5 + drivers/gpu/drm/xe/xe_guc_buf.c | 172 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_guc_buf.h | 47 ++++++++++ drivers/gpu/drm/xe/xe_guc_buf_types.h | 28 ++++++ drivers/gpu/drm/xe/xe_guc_types.h | 3 + 6 files changed, 256 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_guc_buf.c create mode 100644 drivers/gpu/drm/xe/xe_guc_buf.h create mode 100644 drivers/gpu/drm/xe/xe_guc_buf_types.h (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 7730e0596299..2e50a697f549 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -56,6 +56,7 @@ xe-y += xe_bb.o \ xe_gt_topology.o \ xe_guc.o \ xe_guc_ads.o \ + xe_guc_buf.o \ xe_guc_capture.o \ xe_guc_ct.o \ xe_guc_db_mgr.o \ diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index 408365dfe4ee..1619c0a52db9 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -23,6 +23,7 @@ #include "xe_gt_sriov_vf.h" #include "xe_gt_throttle.h" #include "xe_guc_ads.h" +#include "xe_guc_buf.h" #include "xe_guc_capture.h" #include "xe_guc_ct.h" #include "xe_guc_db_mgr.h" @@ -743,6 +744,10 @@ int xe_guc_init_post_hwconfig(struct xe_guc *guc) if (ret) return ret; + ret = xe_guc_buf_cache_init(&guc->buf); + if (ret) + return ret; + return xe_guc_ads_init_post_hwconfig(&guc->ads); } diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c new file mode 100644 index 000000000000..261c7c74417f --- /dev/null +++ b/drivers/gpu/drm/xe/xe_guc_buf.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include +#include + +#include "xe_assert.h" +#include "xe_bo.h" +#include "xe_gt_printk.h" +#include "xe_guc.h" +#include "xe_guc_buf.h" +#include "xe_sa.h" + +static struct xe_guc *cache_to_guc(struct xe_guc_buf_cache *cache) +{ + return container_of(cache, struct xe_guc, buf); +} + +static struct xe_gt *cache_to_gt(struct xe_guc_buf_cache *cache) +{ + return guc_to_gt(cache_to_guc(cache)); +} + +/** + * xe_guc_buf_cache_init() - Initialize the GuC Buffer Cache. + * @cache: the &xe_guc_buf_cache to initialize + * + * The Buffer Cache allows to obtain a reusable buffer that can be used to pass + * indirect H2G data to GuC without a need to create a ad-hoc allocation. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache) +{ + struct xe_gt *gt = cache_to_gt(cache); + struct xe_sa_manager *sam; + + /* XXX: currently it's useful only for the PF actions */ + if (!IS_SRIOV_PF(gt_to_xe(gt))) + return 0; + + sam = __xe_sa_bo_manager_init(gt_to_tile(gt), SZ_8K, 0, sizeof(u32)); + if (IS_ERR(sam)) + return PTR_ERR(sam); + cache->sam = sam; + + xe_gt_dbg(gt, "reusable buffer with %u dwords at %#x for %ps\n", + xe_guc_buf_cache_dwords(cache), xe_bo_ggtt_addr(sam->bo), + __builtin_return_address(0)); + return 0; +} + +/** + * xe_guc_buf_cache_dwords() - Number of dwords the GuC Buffer Cache supports. + * @cache: the &xe_guc_buf_cache to query + * + * Return: a size of the largest reusable buffer (in dwords) + */ +u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache) +{ + return cache->sam ? cache->sam->base.size / sizeof(u32) : 0; +} + +/** + * xe_guc_buf_reserve() - Reserve a new sub-allocation. + * @cache: the &xe_guc_buf_cache where reserve sub-allocation + * @dwords: the requested size of the buffer in dwords + * + * Use xe_guc_buf_is_valid() to check if returned buffer reference is valid. + * Must use xe_guc_buf_release() to release a sub-allocation. + * + * Return: a &xe_guc_buf of new sub-allocation. + */ +struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords) +{ + struct drm_suballoc *sa; + + if (cache->sam) + sa = __xe_sa_bo_new(cache->sam, dwords * sizeof(32), GFP_ATOMIC); + else + sa = ERR_PTR(-EOPNOTSUPP); + + return (struct xe_guc_buf){ .sa = sa }; +} + +/** + * xe_guc_buf_from_data() - Reserve a new sub-allocation using data. + * @cache: the &xe_guc_buf_cache where reserve sub-allocation + * @data: the data to flush the sub-allocation + * @size: the size of the data + * + * Similar to xe_guc_buf_reserve() but flushes @data to the GPU memory. + * + * Return: a &xe_guc_buf of new sub-allocation. + */ +struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache, + const void *data, size_t size) +{ + struct drm_suballoc *sa; + + sa = __xe_sa_bo_new(cache->sam, size, GFP_ATOMIC); + if (!IS_ERR(sa)) + memcpy(xe_sa_bo_cpu_addr(sa), data, size); + + return (struct xe_guc_buf){ .sa = sa }; +} + +/** + * xe_guc_buf_release() - Release a sub-allocation. + * @buf: the &xe_guc_buf to release + * + * Releases a sub-allocation reserved by the xe_guc_buf_reserve(). + */ +void xe_guc_buf_release(const struct xe_guc_buf buf) +{ + if (xe_guc_buf_is_valid(buf)) + xe_sa_bo_free(buf.sa, NULL); +} + +/** + * xe_guc_buf_flush() - Copy the data from the sub-allocation to the GPU memory. + * @buf: the &xe_guc_buf to flush + * + * Return: a GPU address of the sub-allocation. + */ +u64 xe_guc_buf_flush(const struct xe_guc_buf buf) +{ + xe_sa_bo_flush_write(buf.sa); + return xe_sa_bo_gpu_addr(buf.sa); +} + +/** + * xe_guc_buf_cpu_ptr() - Obtain a CPU pointer to the sub-allocation. + * @buf: the &xe_guc_buf to query + * + * Return: a CPU pointer of the sub-allocation. + */ +void *xe_guc_buf_cpu_ptr(const struct xe_guc_buf buf) +{ + return xe_sa_bo_cpu_addr(buf.sa); +} + +/** + * xe_guc_buf_gpu_addr() - Obtain a GPU address of the sub-allocation. + * @buf: the &xe_guc_buf to query + * + * Return: a GPU address of the sub-allocation. + */ +u64 xe_guc_buf_gpu_addr(const struct xe_guc_buf buf) +{ + return xe_sa_bo_gpu_addr(buf.sa); +} + +/** + * xe_guc_cache_gpu_addr_from_ptr() - Lookup a GPU address using the pointer. + * @cache: the &xe_guc_buf_cache with sub-allocations + * @ptr: the CPU pointer of the sub-allocation + * @size: the size of the data + * + * Return: a GPU address on success or 0 if the pointer was unrelated. + */ +u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *ptr, u32 size) +{ + ptrdiff_t offset = ptr - cache->sam->cpu_ptr; + + if (offset < 0 || offset + size > cache->sam->base.size) + return 0; + + return cache->sam->gpu_addr + offset; +} diff --git a/drivers/gpu/drm/xe/xe_guc_buf.h b/drivers/gpu/drm/xe/xe_guc_buf.h new file mode 100644 index 000000000000..0d67604d96bd --- /dev/null +++ b/drivers/gpu/drm/xe/xe_guc_buf.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef _XE_GUC_BUF_H_ +#define _XE_GUC_BUF_H_ + +#include +#include + +#include "xe_guc_buf_types.h" + +int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache); +u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache); +struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords); +struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache, + const void *data, size_t size); +void xe_guc_buf_release(const struct xe_guc_buf buf); + +/** + * xe_guc_buf_is_valid() - Check if a buffer reference is valid. + * @buf: the &xe_guc_buf reference to check + * + * Return: true if @ref represents a valid sub-allication. + */ +static inline bool xe_guc_buf_is_valid(const struct xe_guc_buf buf) +{ + return !IS_ERR_OR_NULL(buf.sa); +} + +void *xe_guc_buf_cpu_ptr(const struct xe_guc_buf buf); +u64 xe_guc_buf_flush(const struct xe_guc_buf buf); +u64 xe_guc_buf_gpu_addr(const struct xe_guc_buf buf); +u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *ptr, u32 size); + +DEFINE_CLASS(xe_guc_buf, struct xe_guc_buf, + xe_guc_buf_release(_T), + xe_guc_buf_reserve(cache, num), + struct xe_guc_buf_cache *cache, u32 num); + +DEFINE_CLASS(xe_guc_buf_from_data, struct xe_guc_buf, + xe_guc_buf_release(_T), + xe_guc_buf_from_data(cache, data, size), + struct xe_guc_buf_cache *cache, const void *data, size_t size); + +#endif diff --git a/drivers/gpu/drm/xe/xe_guc_buf_types.h b/drivers/gpu/drm/xe/xe_guc_buf_types.h new file mode 100644 index 000000000000..9e123d71c064 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_guc_buf_types.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef _XE_GUC_BUF_TYPES_H_ +#define _XE_GUC_BUF_TYPES_H_ + +struct drm_suballoc; +struct xe_sa_manager; + +/** + * struct xe_guc_buf_cache - GuC Data Buffer Cache. + */ +struct xe_guc_buf_cache { + /* private: internal sub-allocation manager */ + struct xe_sa_manager *sam; +}; + +/** + * struct xe_guc_buf - GuC Data Buffer Reference. + */ +struct xe_guc_buf { + /* private: internal sub-allocation reference */ + struct drm_suballoc *sa; +}; + +#endif diff --git a/drivers/gpu/drm/xe/xe_guc_types.h b/drivers/gpu/drm/xe/xe_guc_types.h index 83a41ebcdc91..573aa6308380 100644 --- a/drivers/gpu/drm/xe/xe_guc_types.h +++ b/drivers/gpu/drm/xe/xe_guc_types.h @@ -11,6 +11,7 @@ #include "regs/xe_reg_defs.h" #include "xe_guc_ads_types.h" +#include "xe_guc_buf_types.h" #include "xe_guc_ct_types.h" #include "xe_guc_fwif.h" #include "xe_guc_log_types.h" @@ -58,6 +59,8 @@ struct xe_guc { struct xe_guc_ads ads; /** @ct: GuC ct */ struct xe_guc_ct ct; + /** @buf: GuC Buffer Cache manager */ + struct xe_guc_buf_cache buf; /** @capture: the error-state-capture module's data and objects */ struct xe_guc_state_capture *capture; /** @pc: GuC Power Conservation */ -- cgit v1.2.3-59-g8ed1b From d8b2149ba8f184cd138b482289b16d8558787e99 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:42:02 +0100 Subject: drm/xe/pf: Use GuC Buffer Cache during VFs provisioning Start using GuC buffer cache for the VF's configuration actions. Signed-off-by: Michal Wajdeczko Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-10-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 68 +++++++++++++++--------------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 878e96281c03..9db1c920219d 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -20,6 +20,7 @@ #include "xe_gt_sriov_pf_policy.h" #include "xe_gt_sriov_printk.h" #include "xe_guc.h" +#include "xe_guc_buf.h" #include "xe_guc_ct.h" #include "xe_guc_db_mgr.h" #include "xe_guc_fwif.h" @@ -71,48 +72,27 @@ static int pf_send_vf_cfg_reset(struct xe_gt *gt, u32 vfid) * Return: number of KLVs that were successfully parsed and saved, * negative error code on failure. */ -static int pf_send_vf_cfg_klvs(struct xe_gt *gt, u32 vfid, const u32 *klvs, u32 num_dwords) +static int pf_send_vf_buf_klvs(struct xe_gt *gt, u32 vfid, struct xe_guc_buf buf, u32 num_dwords) { - const u32 bytes = num_dwords * sizeof(u32); - struct xe_tile *tile = gt_to_tile(gt); - struct xe_device *xe = tile_to_xe(tile); struct xe_guc *guc = >->uc.guc; - struct xe_bo *bo; - int ret; - bo = xe_bo_create_pin_map(xe, tile, NULL, - ALIGN(bytes, PAGE_SIZE), - ttm_bo_type_kernel, - XE_BO_FLAG_VRAM_IF_DGFX(tile) | - XE_BO_FLAG_GGTT | - XE_BO_FLAG_GGTT_INVALIDATE); - if (IS_ERR(bo)) - return PTR_ERR(bo); - - xe_map_memcpy_to(xe, &bo->vmap, 0, klvs, bytes); - - ret = guc_action_update_vf_cfg(guc, vfid, xe_bo_ggtt_addr(bo), num_dwords); - - xe_bo_unpin_map_no_vm(bo); - - return ret; + return guc_action_update_vf_cfg(guc, vfid, xe_guc_buf_flush(buf), num_dwords); } /* * Return: 0 on success, -ENOKEY if some KLVs were not updated, -EPROTO if reply was malformed, * negative error code on failure. */ -static int pf_push_vf_cfg_klvs(struct xe_gt *gt, unsigned int vfid, u32 num_klvs, - const u32 *klvs, u32 num_dwords) +static int pf_push_vf_buf_klvs(struct xe_gt *gt, unsigned int vfid, u32 num_klvs, + struct xe_guc_buf buf, u32 num_dwords) { int ret; - xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); - - ret = pf_send_vf_cfg_klvs(gt, vfid, klvs, num_dwords); + ret = pf_send_vf_buf_klvs(gt, vfid, buf, num_dwords); if (ret != num_klvs) { int err = ret < 0 ? ret : ret < num_klvs ? -ENOKEY : -EPROTO; + void *klvs = xe_guc_buf_cpu_ptr(buf); struct drm_printer p = xe_gt_info_printer(gt); char name[8]; @@ -125,13 +105,35 @@ static int pf_push_vf_cfg_klvs(struct xe_gt *gt, unsigned int vfid, u32 num_klvs if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV)) { struct drm_printer p = xe_gt_info_printer(gt); + void *klvs = xe_guc_buf_cpu_ptr(buf); + char name[8]; + xe_gt_sriov_info(gt, "pushed %s config with %u KLV%s:\n", + xe_sriov_function_name(vfid, name, sizeof(name)), + num_klvs, str_plural(num_klvs)); xe_guc_klv_print(klvs, num_dwords, &p); } return 0; } +/* + * Return: 0 on success, -ENOBUFS if no free buffer for the indirect data, + * negative error code on failure. + */ +static int pf_push_vf_cfg_klvs(struct xe_gt *gt, unsigned int vfid, u32 num_klvs, + const u32 *klvs, u32 num_dwords) +{ + CLASS(xe_guc_buf_from_data, buf)(>->uc.guc.buf, klvs, num_dwords * sizeof(u32)); + + xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); + + if (!xe_guc_buf_is_valid(buf)) + return -ENOBUFS; + + return pf_push_vf_buf_klvs(gt, vfid, num_klvs, buf, num_dwords); +} + static int pf_push_vf_cfg_u32(struct xe_gt *gt, unsigned int vfid, u16 key, u32 value) { u32 klv[] = { @@ -304,16 +306,17 @@ static u32 encode_config(u32 *cfg, const struct xe_gt_sriov_config *config, bool static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) { struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); - u32 max_cfg_dwords = SZ_4K / sizeof(u32); + u32 max_cfg_dwords = xe_guc_buf_cache_dwords(>->uc.guc.buf); + CLASS(xe_guc_buf, buf)(>->uc.guc.buf, max_cfg_dwords); u32 num_dwords; int num_klvs; u32 *cfg; int err; - cfg = kcalloc(max_cfg_dwords, sizeof(u32), GFP_KERNEL); - if (!cfg) - return -ENOMEM; + if (!xe_guc_buf_is_valid(buf)) + return -ENOBUFS; + cfg = xe_guc_buf_cpu_ptr(buf); num_dwords = encode_config(cfg, config, true); xe_gt_assert(gt, num_dwords <= max_cfg_dwords); @@ -330,9 +333,8 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) xe_gt_assert(gt, num_dwords <= max_cfg_dwords); num_klvs = xe_guc_klv_count(cfg, num_dwords); - err = pf_push_vf_cfg_klvs(gt, vfid, num_klvs, cfg, num_dwords); + err = pf_push_vf_buf_klvs(gt, vfid, num_klvs, buf, num_dwords); - kfree(cfg); return err; } -- cgit v1.2.3-59-g8ed1b From f90b552dcbb4e142f2a15d2b4458ea601248b8e8 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 20 Dec 2024 20:42:03 +0100 Subject: drm/xe/kunit: Allow to replace xe_managed_bo_create_pin_map() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to use replacement functions in upcoming kunit tests. Signed-off-by: Michal Wajdeczko Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-11-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_bo.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index cf0dc9e9c53e..c32201123d44 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -15,6 +15,8 @@ #include #include +#include + #include "xe_device.h" #include "xe_dma_buf.h" #include "xe_drm_client.h" @@ -1797,6 +1799,8 @@ struct xe_bo *xe_managed_bo_create_pin_map(struct xe_device *xe, struct xe_tile struct xe_bo *bo; int ret; + KUNIT_STATIC_STUB_REDIRECT(xe_managed_bo_create_pin_map, xe, tile, size, flags); + bo = xe_bo_create_pin_map(xe, tile, NULL, size, ttm_bo_type_kernel, flags); if (IS_ERR(bo)) return bo; -- cgit v1.2.3-59-g8ed1b From 238f96315ada9e2183b04df90c9714b1da68455c Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 14 Jan 2025 20:21:40 +0100 Subject: drm/xe/kunit: Add KUnit tests for GuC Buffer Cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add tests to make sure that recently added GuC Buffer Cache component is working as expected. Signed-off-by: Michal Wajdeczko Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20250114192140.1039-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c | 334 ++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_guc_buf.c | 4 + 2 files changed, 338 insertions(+) create mode 100644 drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c new file mode 100644 index 000000000000..6faffcd74869 --- /dev/null +++ b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: GPL-2.0 AND MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include +#include +#include + +#include "xe_device.h" +#include "xe_ggtt.h" +#include "xe_guc_ct.h" +#include "xe_kunit_helpers.h" +#include "xe_pci_test.h" + +#define DUT_GGTT_START SZ_1M +#define DUT_GGTT_SIZE SZ_2M + +static struct xe_bo *replacement_xe_managed_bo_create_pin_map(struct xe_device *xe, + struct xe_tile *tile, + size_t size, u32 flags) +{ + struct kunit *test = kunit_get_current_test(); + struct xe_bo *bo; + void *buf; + + bo = drmm_kzalloc(&xe->drm, sizeof(*bo), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo); + + buf = drmm_kzalloc(&xe->drm, size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + + bo->tile = tile; + bo->ttm.bdev = &xe->ttm; + bo->size = size; + iosys_map_set_vaddr(&bo->vmap, buf); + + if (flags & XE_BO_FLAG_GGTT) { + struct xe_ggtt *ggtt = tile->mem.ggtt; + + bo->ggtt_node[tile->id] = xe_ggtt_node_init(ggtt); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo->ggtt_node[tile->id]); + + KUNIT_ASSERT_EQ(test, 0, + drm_mm_insert_node_in_range(&ggtt->mm, + &bo->ggtt_node[tile->id]->base, + bo->size, SZ_4K, + 0, 0, U64_MAX, 0)); + } + + return bo; +} + +static int guc_buf_test_init(struct kunit *test) +{ + struct xe_pci_fake_data fake = { + .sriov_mode = XE_SRIOV_MODE_PF, + .platform = XE_TIGERLAKE, /* some random platform */ + .subplatform = XE_SUBPLATFORM_NONE, + }; + struct xe_ggtt *ggtt; + struct xe_guc *guc; + + test->priv = &fake; + xe_kunit_helper_xe_device_test_init(test); + + ggtt = xe_device_get_root_tile(test->priv)->mem.ggtt; + guc = &xe_device_get_gt(test->priv, 0)->uc.guc; + + drm_mm_init(&ggtt->mm, DUT_GGTT_START, DUT_GGTT_SIZE); + mutex_init(&ggtt->lock); + + kunit_activate_static_stub(test, xe_managed_bo_create_pin_map, + replacement_xe_managed_bo_create_pin_map); + + KUNIT_ASSERT_EQ(test, 0, xe_guc_buf_cache_init(&guc->buf)); + + test->priv = &guc->buf; + return 0; +} + +static void test_smallest(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf buf; + + buf = xe_guc_buf_reserve(cache, 1); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); + xe_guc_buf_release(buf); +} + +static void test_largest(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf buf; + + buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); + xe_guc_buf_release(buf); +} + +static void test_granular(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf *bufs; + int n, dwords; + + dwords = xe_guc_buf_cache_dwords(cache); + bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL); + KUNIT_EXPECT_NOT_NULL(test, bufs); + + for (n = 0; n < dwords; n++) + bufs[n] = xe_guc_buf_reserve(cache, 1); + + for (n = 0; n < dwords; n++) + KUNIT_EXPECT_TRUE_MSG(test, xe_guc_buf_is_valid(bufs[n]), "n=%d", n); + + for (n = 0; n < dwords; n++) + xe_guc_buf_release(bufs[n]); +} + +static void test_unique(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf *bufs; + int n, m, dwords; + + dwords = xe_guc_buf_cache_dwords(cache); + bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL); + KUNIT_EXPECT_NOT_NULL(test, bufs); + + for (n = 0; n < dwords; n++) + bufs[n] = xe_guc_buf_reserve(cache, 1); + + for (n = 0; n < dwords; n++) { + for (m = n + 1; m < dwords; m++) { + KUNIT_EXPECT_PTR_NE_MSG(test, xe_guc_buf_cpu_ptr(bufs[n]), + xe_guc_buf_cpu_ptr(bufs[m]), "n=%d, m=%d", n, m); + KUNIT_ASSERT_NE_MSG(test, xe_guc_buf_gpu_addr(bufs[n]), + xe_guc_buf_gpu_addr(bufs[m]), "n=%d, m=%d", n, m); + } + } + + for (n = 0; n < dwords; n++) + xe_guc_buf_release(bufs[n]); +} + +static void test_overlap(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf b1, b2; + u32 dwords = xe_guc_buf_cache_dwords(cache) / 2; + u32 bytes = dwords * sizeof(u32); + void *p1, *p2; + u64 a1, a2; + + b1 = xe_guc_buf_reserve(cache, dwords); + b2 = xe_guc_buf_reserve(cache, dwords); + + p1 = xe_guc_buf_cpu_ptr(b1); + p2 = xe_guc_buf_cpu_ptr(b2); + + a1 = xe_guc_buf_gpu_addr(b1); + a2 = xe_guc_buf_gpu_addr(b2); + + KUNIT_EXPECT_PTR_NE(test, p1, p2); + if (p1 < p2) + KUNIT_EXPECT_LT(test, (uintptr_t)(p1 + bytes - 1), (uintptr_t)p2); + else + KUNIT_EXPECT_LT(test, (uintptr_t)(p2 + bytes - 1), (uintptr_t)p1); + + KUNIT_EXPECT_NE(test, a1, a2); + if (a1 < a2) + KUNIT_EXPECT_LT(test, a1 + bytes - 1, a2); + else + KUNIT_EXPECT_LT(test, a2 + bytes - 1, a1); + + xe_guc_buf_release(b1); + xe_guc_buf_release(b2); +} + +static void test_reusable(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf b1, b2; + void *p1; + u64 a1; + + b1 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(b1)); + KUNIT_EXPECT_NOT_NULL(test, p1 = xe_guc_buf_cpu_ptr(b1)); + KUNIT_EXPECT_NE(test, 0, a1 = xe_guc_buf_gpu_addr(b1)); + xe_guc_buf_release(b1); + + b2 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); + KUNIT_EXPECT_PTR_EQ(test, p1, xe_guc_buf_cpu_ptr(b2)); + KUNIT_EXPECT_EQ(test, a1, xe_guc_buf_gpu_addr(b2)); + xe_guc_buf_release(b2); +} + +static void test_too_big(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf buf; + + buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache) + 1); + KUNIT_EXPECT_FALSE(test, xe_guc_buf_is_valid(buf)); + xe_guc_buf_release(buf); /* shouldn't crash */ +} + +static void test_flush(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf buf; + const u32 dwords = xe_guc_buf_cache_dwords(cache); + const u32 bytes = dwords * sizeof(u32); + u32 *s, *p, *d; + int n; + + KUNIT_ASSERT_NOT_NULL(test, s = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL)); + KUNIT_ASSERT_NOT_NULL(test, d = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL)); + + for (n = 0; n < dwords; n++) + s[n] = n; + + buf = xe_guc_buf_reserve(cache, dwords); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); + KUNIT_EXPECT_PTR_NE(test, p, s); + KUNIT_EXPECT_PTR_NE(test, p, d); + + memcpy(p, s, bytes); + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_flush(buf)); + + iosys_map_memcpy_from(d, &cache->sam->bo->vmap, 0, bytes); + KUNIT_EXPECT_MEMEQ(test, s, d, bytes); + + xe_guc_buf_release(buf); +} + +static void test_lookup(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf buf; + u32 dwords; + u64 addr; + u32 *p; + int n; + + dwords = xe_guc_buf_cache_dwords(cache); + buf = xe_guc_buf_reserve(cache, dwords); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); + KUNIT_ASSERT_NE(test, 0, addr = xe_guc_buf_gpu_addr(buf)); + + KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p - 1, sizeof(u32))); + KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p + dwords, sizeof(u32))); + + for (n = 0; n < dwords; n++) + KUNIT_EXPECT_EQ_MSG(test, xe_guc_cache_gpu_addr_from_ptr(cache, p + n, sizeof(u32)), + addr + n * sizeof(u32), "n=%d", n); + + xe_guc_buf_release(buf); +} + +static void test_data(struct kunit *test) +{ + static const u32 data[] = { 1, 2, 3, 4, 5, 6 }; + struct xe_guc_buf_cache *cache = test->priv; + struct xe_guc_buf buf; + void *p; + + buf = xe_guc_buf_from_data(cache, data, sizeof(data)); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); + KUNIT_EXPECT_MEMEQ(test, p, data, sizeof(data)); + + xe_guc_buf_release(buf); +} + +static void test_class(struct kunit *test) +{ + struct xe_guc_buf_cache *cache = test->priv; + u32 dwords = xe_guc_buf_cache_dwords(cache); + + { + CLASS(xe_guc_buf, buf)(cache, dwords); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); + } + + { + CLASS(xe_guc_buf, buf)(cache, dwords); + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); + } +} + +static struct kunit_case guc_buf_test_cases[] = { + KUNIT_CASE(test_smallest), + KUNIT_CASE(test_largest), + KUNIT_CASE(test_granular), + KUNIT_CASE(test_unique), + KUNIT_CASE(test_overlap), + KUNIT_CASE(test_reusable), + KUNIT_CASE(test_too_big), + KUNIT_CASE(test_flush), + KUNIT_CASE(test_lookup), + KUNIT_CASE(test_data), + KUNIT_CASE(test_class), + {} +}; + +static struct kunit_suite guc_buf_suite = { + .name = "guc_buf", + .test_cases = guc_buf_test_cases, + .init = guc_buf_test_init, +}; + +kunit_test_suites(&guc_buf_suite); diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c index 261c7c74417f..ce6d9830e13b 100644 --- a/drivers/gpu/drm/xe/xe_guc_buf.c +++ b/drivers/gpu/drm/xe/xe_guc_buf.c @@ -170,3 +170,7 @@ u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *p return cache->sam->gpu_addr + offset; } + +#if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST) +#include "tests/xe_guc_buf_kunit.c" +#endif -- cgit v1.2.3-59-g8ed1b From 173baa1b2dc44e3551d9414f4919a48fe5da4880 Mon Sep 17 00:00:00 2001 From: Satyanarayana K V P Date: Thu, 16 Jan 2025 11:26:17 +0530 Subject: drm/xe: Suppress printing of mode when running in non-sriov mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xe_sriov_probe_early() function prints the sriov pf/vf mode on driver probe. When running in non-sriov mode, the below debug message is seen. "Running in none mode". This print does not convey any information. This commit suppresses this debug message and shows only when running in PF/VF mode. Signed-off-by: Satyanarayana K V P Cc: Michał Wajdeczko Reviewed-by: Lucas De Marchi Signed-off-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20250116055617.20611-1-satyanarayana.k.v.p@intel.com --- drivers/gpu/drm/xe/xe_sriov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_sriov.c b/drivers/gpu/drm/xe/xe_sriov.c index 04e2f539ccd9..a0eab44c0e76 100644 --- a/drivers/gpu/drm/xe/xe_sriov.c +++ b/drivers/gpu/drm/xe/xe_sriov.c @@ -81,7 +81,7 @@ void xe_sriov_probe_early(struct xe_device *xe) xe->sriov.__mode = mode; xe_assert(xe, xe->sriov.__mode); - if (has_sriov) + if (IS_SRIOV(xe)) drm_info(&xe->drm, "Running in %s mode\n", xe_sriov_mode_to_string(xe_device_sriov_mode(xe))); } -- cgit v1.2.3-59-g8ed1b From 6568d423cb3000789b2b8493049883fcec09c329 Mon Sep 17 00:00:00 2001 From: Vivek Kasireddy Date: Mon, 13 Jan 2025 23:57:59 -0800 Subject: drm/virtio: Don't return error if virtio-gpu PCI dev is not found While fixing a shared VGA resource ownership issue, commit 5dd8b536bbda ("drm/virtio: Lock the VGA resources during initialization") wrongly assumed that there is always a PCI device associated with virtio-gpu and it would return error if this device is not found during init. This is incorrect, as virtio-gpu can be operated in MMIO mode (M68K) where a PCI device would probably not be created for it. Therefore, fix this issue by not erroring out if the associated PCI device is not found during initialization. Fixes: 5dd8b536bbda ("drm/virtio: Lock the VGA resources during initialization") Suggested-by: Dmitry Osipenko Cc: Gerd Hoffmann Cc: Gurchetan Singh Cc: Chia-I Wu Signed-off-by: Vivek Kasireddy Link: https://patchwork.freedesktop.org/patch/msgid/20250114075759.2616551-1-vivek.kasireddy@intel.com Reviewed-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20250114075759.2616551-1-vivek.kasireddy@intel.com --- drivers/gpu/drm/virtio/virtgpu_drv.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index d4309dba557b..2d88e390feb4 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -173,23 +173,24 @@ static int __init virtio_gpu_driver_init(void) pdev = pci_get_device(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_GPU, NULL); - if (!pdev) - return -ENODEV; - - if (pci_is_vga(pdev)) { + if (pdev && pci_is_vga(pdev)) { ret = vga_get_interruptible(pdev, VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); - if (ret) - goto error; + if (ret) { + pci_dev_put(pdev); + return ret; + } } ret = register_virtio_driver(&virtio_gpu_driver); - if (pci_is_vga(pdev)) - vga_put(pdev, VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); + if (pdev) { + if (pci_is_vga(pdev)) + vga_put(pdev, + VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); -error: - pci_dev_put(pdev); + pci_dev_put(pdev); + } return ret; } -- cgit v1.2.3-59-g8ed1b From 04630796c437a9285643097825cbd3cd06603f47 Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Fri, 20 Dec 2024 10:37:07 -0300 Subject: drm/vc4: Use DRM Execution Contexts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VC4 has internal copies of `drm_gem_lock_reservations()` and `drm_gem_unlock_reservations()` within the driver. Ideally, these hard-coded functions should be replaced with the generic functions provided by DRM common code. However, instead of using the DRM GEM functions to (un)lock reservations, transition to the new DRM Execution Contexts API. Signed-off-by: Maíra Canal Acked-by: Christian König Reviewed-by: Melissa Wen Link: https://patchwork.freedesktop.org/patch/msgid/20241220134204.634577-2-mcanal@igalia.com --- drivers/gpu/drm/vc4/Kconfig | 1 + drivers/gpu/drm/vc4/vc4_gem.c | 99 +++++++++---------------------------------- 2 files changed, 22 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index 6cc7b7e6294a..123ab0ce1781 100644 --- a/drivers/gpu/drm/vc4/Kconfig +++ b/drivers/gpu/drm/vc4/Kconfig @@ -14,6 +14,7 @@ config DRM_VC4 select DRM_DISPLAY_HDMI_HELPER select DRM_DISPLAY_HDMI_STATE_HELPER select DRM_DISPLAY_HELPER + select DRM_EXEC select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 22bccd69eb62..1021f45cb53c 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -29,6 +29,7 @@ #include #include +#include #include #include "uapi/drm/vc4_drm.h" @@ -578,19 +579,6 @@ vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) } } -static void -vc4_unlock_bo_reservations(struct drm_device *dev, - struct vc4_exec_info *exec, - struct ww_acquire_ctx *acquire_ctx) -{ - int i; - - for (i = 0; i < exec->bo_count; i++) - dma_resv_unlock(exec->bo[i]->resv); - - ww_acquire_fini(acquire_ctx); -} - /* Takes the reservation lock on all the BOs being referenced, so that * at queue submit time we can update the reservations. * @@ -599,70 +587,23 @@ vc4_unlock_bo_reservations(struct drm_device *dev, * to vc4, so we don't attach dma-buf fences to them. */ static int -vc4_lock_bo_reservations(struct drm_device *dev, - struct vc4_exec_info *exec, - struct ww_acquire_ctx *acquire_ctx) +vc4_lock_bo_reservations(struct vc4_exec_info *exec, + struct drm_exec *exec_ctx) { - int contended_lock = -1; - int i, ret; - struct drm_gem_object *bo; - - ww_acquire_init(acquire_ctx, &reservation_ww_class); - -retry: - if (contended_lock != -1) { - bo = exec->bo[contended_lock]; - ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); - if (ret) { - ww_acquire_done(acquire_ctx); - return ret; - } - } - - for (i = 0; i < exec->bo_count; i++) { - if (i == contended_lock) - continue; - - bo = exec->bo[i]; - - ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); - if (ret) { - int j; - - for (j = 0; j < i; j++) { - bo = exec->bo[j]; - dma_resv_unlock(bo->resv); - } - - if (contended_lock != -1 && contended_lock >= i) { - bo = exec->bo[contended_lock]; - - dma_resv_unlock(bo->resv); - } - - if (ret == -EDEADLK) { - contended_lock = i; - goto retry; - } - - ww_acquire_done(acquire_ctx); - return ret; - } - } - - ww_acquire_done(acquire_ctx); + int ret; /* Reserve space for our shared (read-only) fence references, * before we commit the CL to the hardware. */ - for (i = 0; i < exec->bo_count; i++) { - bo = exec->bo[i]; + drm_exec_init(exec_ctx, DRM_EXEC_INTERRUPTIBLE_WAIT, exec->bo_count); + drm_exec_until_all_locked(exec_ctx) { + ret = drm_exec_prepare_array(exec_ctx, exec->bo, + exec->bo_count, 1); + } - ret = dma_resv_reserve_fences(bo->resv, 1); - if (ret) { - vc4_unlock_bo_reservations(dev, exec, acquire_ctx); - return ret; - } + if (ret) { + drm_exec_fini(exec_ctx); + return ret; } return 0; @@ -679,7 +620,7 @@ retry: */ static int vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, - struct ww_acquire_ctx *acquire_ctx, + struct drm_exec *exec_ctx, struct drm_syncobj *out_sync) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -708,7 +649,7 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, vc4_update_bo_seqnos(exec, seqno); - vc4_unlock_bo_reservations(dev, exec, acquire_ctx); + drm_exec_fini(exec_ctx); list_add_tail(&exec->head, &vc4->bin_job_list); @@ -1123,7 +1064,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, struct drm_vc4_submit_cl *args = data; struct drm_syncobj *out_sync = NULL; struct vc4_exec_info *exec; - struct ww_acquire_ctx acquire_ctx; + struct drm_exec exec_ctx; struct dma_fence *in_fence; int ret = 0; @@ -1216,7 +1157,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, if (ret) goto fail; - ret = vc4_lock_bo_reservations(dev, exec, &acquire_ctx); + ret = vc4_lock_bo_reservations(exec, &exec_ctx); if (ret) goto fail; @@ -1224,7 +1165,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, out_sync = drm_syncobj_find(file_priv, args->out_sync); if (!out_sync) { ret = -EINVAL; - goto fail; + goto fail_unreserve; } /* We replace the fence in out_sync in vc4_queue_submit since @@ -1239,7 +1180,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, */ exec->args = NULL; - ret = vc4_queue_submit(dev, exec, &acquire_ctx, out_sync); + ret = vc4_queue_submit(dev, exec, &exec_ctx, out_sync); /* The syncobj isn't part of the exec data and we need to free our * reference even if job submission failed. @@ -1248,13 +1189,15 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, drm_syncobj_put(out_sync); if (ret) - goto fail; + goto fail_unreserve; /* Return the seqno for our job. */ args->seqno = vc4->emit_seqno; return 0; +fail_unreserve: + drm_exec_fini(&exec_ctx); fail: vc4_complete_exec(&vc4->base, exec); -- cgit v1.2.3-59-g8ed1b From 21bd85f82ec20ddfc65ae999f49356c86fb68a8d Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Fri, 20 Dec 2024 10:37:08 -0300 Subject: drm/vc4: Use DMA Resv to implement VC4 wait BO IOCTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the BOs used by VC4 have DMA Reservation Objects attached to them, waiting for seqnos to check BO availability is unnecessary. Instead, `drm_gem_dma_resv_wait()` can be used. Signed-off-by: Maíra Canal Reviewed-by: Melissa Wen Link: https://patchwork.freedesktop.org/patch/msgid/20241220134204.634577-3-mcanal@igalia.com --- drivers/gpu/drm/vc4/vc4_gem.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 1021f45cb53c..de7be9942c13 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -1020,8 +1020,10 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, struct vc4_dev *vc4 = to_vc4_dev(dev); int ret; struct drm_vc4_wait_bo *args = data; - struct drm_gem_object *gem_obj; - struct vc4_bo *bo; + unsigned long timeout_jiffies = + usecs_to_jiffies(div_u64(args->timeout_ns, 1000)); + ktime_t start = ktime_get(); + u64 delta_ns; if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return -ENODEV; @@ -1029,17 +1031,18 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, if (args->pad != 0) return -EINVAL; - gem_obj = drm_gem_object_lookup(file_priv, args->handle); - if (!gem_obj) { - DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle); - return -EINVAL; - } - bo = to_vc4_bo(gem_obj); + ret = drm_gem_dma_resv_wait(file_priv, args->handle, + true, timeout_jiffies); - ret = vc4_wait_for_seqno_ioctl_helper(dev, bo->seqno, - &args->timeout_ns); + /* Decrement the user's timeout, in case we got interrupted + * such that the ioctl will be restarted. + */ + delta_ns = ktime_to_ns(ktime_sub(ktime_get(), start)); + if (delta_ns < args->timeout_ns) + args->timeout_ns -= delta_ns; + else + args->timeout_ns = 0; - drm_gem_object_put(gem_obj); return ret; } -- cgit v1.2.3-59-g8ed1b From e8941ac97f281ffa06d6ed058b3bba676f3f8183 Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Fri, 20 Dec 2024 10:37:09 -0300 Subject: drm/vc4: Remove BOs seqnos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `bo->seqno`, `bo->write_seqno`, and `exec->bin_dep_seqno` are leftovers from a time when VC4 didn't support DMA Reservation Objects. Before DMA Resv was introduced, tracking the correspondence between BOs and jobs through the job's seqno made sense. However, this is no longer needed, as VC4 now supports DMA Reservation Objects and attaches the "job done" fence to the BOs. Therefore, remove the BOs seqnos in favor of using DMA Resv Objects. Signed-off-by: Maíra Canal Reviewed-by: Maxime Ripard Reviewed-by: Melissa Wen Link: https://patchwork.freedesktop.org/patch/msgid/20241220134204.634577-4-mcanal@igalia.com --- drivers/gpu/drm/vc4/vc4_crtc.c | 33 ++++++++++----------- drivers/gpu/drm/vc4/vc4_drv.h | 27 ----------------- drivers/gpu/drm/vc4/vc4_gem.c | 59 ++------------------------------------ drivers/gpu/drm/vc4/vc4_validate.c | 11 ------- 4 files changed, 17 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index cf40a53ad42e..2a48038abe7a 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -884,11 +884,7 @@ struct vc4_async_flip_state { struct drm_framebuffer *fb; struct drm_framebuffer *old_fb; struct drm_pending_vblank_event *event; - - union { - struct dma_fence_cb fence; - struct vc4_seqno_cb seqno; - } cb; + struct dma_fence_cb cb; }; /* Called when the V3D execution for the BO being flipped to is done, so that @@ -919,10 +915,11 @@ vc4_async_page_flip_complete(struct vc4_async_flip_state *flip_state) kfree(flip_state); } -static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) +static void vc4_async_page_flip_complete_with_cleanup(struct dma_fence *fence, + struct dma_fence_cb *cb) { struct vc4_async_flip_state *flip_state = - container_of(cb, struct vc4_async_flip_state, cb.seqno); + container_of(cb, struct vc4_async_flip_state, cb); struct vc4_bo *bo = NULL; if (flip_state->old_fb) { @@ -932,6 +929,7 @@ static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) } vc4_async_page_flip_complete(flip_state); + dma_fence_put(fence); /* * Decrement the BO usecnt in order to keep the inc/dec @@ -950,7 +948,7 @@ static void vc4_async_page_flip_fence_complete(struct dma_fence *fence, struct dma_fence_cb *cb) { struct vc4_async_flip_state *flip_state = - container_of(cb, struct vc4_async_flip_state, cb.fence); + container_of(cb, struct vc4_async_flip_state, cb); vc4_async_page_flip_complete(flip_state); dma_fence_put(fence); @@ -961,16 +959,15 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, { struct drm_framebuffer *fb = flip_state->fb; struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0); + dma_fence_func_t async_page_flip_complete_function; struct vc4_dev *vc4 = to_vc4_dev(dev); struct dma_fence *fence; int ret; - if (vc4->gen == VC4_GEN_4) { - 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); - } + if (vc4->gen == VC4_GEN_4) + async_page_flip_complete_function = vc4_async_page_flip_complete_with_cleanup; + else + async_page_flip_complete_function = vc4_async_page_flip_fence_complete; ret = dma_resv_get_singleton(dma_bo->base.resv, DMA_RESV_USAGE_READ, &fence); if (ret) @@ -978,14 +975,14 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, /* If there's no fence, complete the page flip immediately */ if (!fence) { - vc4_async_page_flip_fence_complete(fence, &flip_state->cb.fence); + async_page_flip_complete_function(fence, &flip_state->cb); return 0; } /* If the fence has already been completed, complete the page flip */ - if (dma_fence_add_callback(fence, &flip_state->cb.fence, - vc4_async_page_flip_fence_complete)) - vc4_async_page_flip_fence_complete(fence, &flip_state->cb.fence); + if (dma_fence_add_callback(fence, &flip_state->cb, + async_page_flip_complete_function)) + async_page_flip_complete_function(fence, &flip_state->cb); return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 4a078ffd9f82..221d8e01d539 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -186,11 +186,6 @@ struct vc4_dev { */ struct vc4_perfmon *active_perfmon; - /* List of struct vc4_seqno_cb for callbacks to be made from a - * workqueue when the given seqno is passed. - */ - struct list_head seqno_cb_list; - /* The memory used for storing binner tile alloc, tile state, * and overflow memory allocations. This is freed when V3D * powers down. @@ -247,16 +242,6 @@ struct vc4_dev { struct vc4_bo { struct drm_gem_dma_object base; - /* seqno of the last job to render using this BO. */ - uint64_t seqno; - - /* seqno of the last job to use the RCL to write to this BO. - * - * Note that this doesn't include binner overflow memory - * writes. - */ - uint64_t write_seqno; - bool t_format; /* List entry for the BO's position in either @@ -304,12 +289,6 @@ struct vc4_fence { #define to_vc4_fence(_fence) \ container_of_const(_fence, struct vc4_fence, base) -struct vc4_seqno_cb { - struct work_struct work; - uint64_t seqno; - void (*func)(struct vc4_seqno_cb *cb); -}; - struct vc4_v3d { struct vc4_dev *vc4; struct platform_device *pdev; @@ -695,9 +674,6 @@ struct vc4_exec_info { /* Sequence number for this bin/render job. */ uint64_t seqno; - /* Latest write_seqno of any BO that binning depends on. */ - uint64_t bin_dep_seqno; - struct dma_fence *fence; /* Last current addresses the hardware was processing when the @@ -1025,9 +1001,6 @@ void vc4_move_job_to_render(struct drm_device *dev, struct vc4_exec_info *exec); int vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns, bool interruptible); void vc4_job_handle_completed(struct vc4_dev *vc4); -int vc4_queue_seqno_cb(struct drm_device *dev, - struct vc4_seqno_cb *cb, uint64_t seqno, - void (*func)(struct vc4_seqno_cb *cb)); int vc4_gem_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index de7be9942c13..8125f87edc60 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -553,27 +553,19 @@ vc4_move_job_to_render(struct drm_device *dev, struct vc4_exec_info *exec) } static void -vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) +vc4_attach_fences(struct vc4_exec_info *exec) { struct vc4_bo *bo; unsigned i; for (i = 0; i < exec->bo_count; i++) { bo = to_vc4_bo(exec->bo[i]); - bo->seqno = seqno; - dma_resv_add_fence(bo->base.base.resv, exec->fence, DMA_RESV_USAGE_READ); } - list_for_each_entry(bo, &exec->unref_list, unref_head) { - bo->seqno = seqno; - } - for (i = 0; i < exec->rcl_write_bo_count; i++) { bo = to_vc4_bo(&exec->rcl_write_bo[i]->base); - bo->write_seqno = seqno; - dma_resv_add_fence(bo->base.base.resv, exec->fence, DMA_RESV_USAGE_WRITE); } @@ -647,7 +639,7 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, if (out_sync) drm_syncobj_replace_fence(out_sync, exec->fence); - vc4_update_bo_seqnos(exec, seqno); + vc4_attach_fences(exec); drm_exec_fini(exec_ctx); @@ -845,12 +837,6 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) goto fail; } - /* Block waiting on any previous rendering into the CS's VBO, - * IB, or textures, so that pixels are actually written by the - * time we try to read them. - */ - ret = vc4_wait_for_seqno(dev, exec->bin_dep_seqno, ~0ull, true); - fail: kvfree(temp); return ret; @@ -909,7 +895,6 @@ void vc4_job_handle_completed(struct vc4_dev *vc4) { unsigned long irqflags; - struct vc4_seqno_cb *cb, *cb_temp; if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return; @@ -926,48 +911,9 @@ vc4_job_handle_completed(struct vc4_dev *vc4) spin_lock_irqsave(&vc4->job_lock, irqflags); } - list_for_each_entry_safe(cb, cb_temp, &vc4->seqno_cb_list, work.entry) { - if (cb->seqno <= vc4->finished_seqno) { - list_del_init(&cb->work.entry); - schedule_work(&cb->work); - } - } - spin_unlock_irqrestore(&vc4->job_lock, irqflags); } -static void vc4_seqno_cb_work(struct work_struct *work) -{ - struct vc4_seqno_cb *cb = container_of(work, struct vc4_seqno_cb, work); - - cb->func(cb); -} - -int vc4_queue_seqno_cb(struct drm_device *dev, - struct vc4_seqno_cb *cb, uint64_t seqno, - void (*func)(struct vc4_seqno_cb *cb)) -{ - struct vc4_dev *vc4 = to_vc4_dev(dev); - unsigned long irqflags; - - if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) - return -ENODEV; - - cb->func = func; - INIT_WORK(&cb->work, vc4_seqno_cb_work); - - spin_lock_irqsave(&vc4->job_lock, irqflags); - if (seqno > vc4->finished_seqno) { - cb->seqno = seqno; - list_add_tail(&cb->work.entry, &vc4->seqno_cb_list); - } else { - schedule_work(&cb->work); - } - spin_unlock_irqrestore(&vc4->job_lock, irqflags); - - return 0; -} - /* Scheduled when any job has been completed, this walks the list of * jobs that had completed and unrefs their BOs and frees their exec * structs. @@ -1221,7 +1167,6 @@ int vc4_gem_init(struct drm_device *dev) INIT_LIST_HEAD(&vc4->bin_job_list); INIT_LIST_HEAD(&vc4->render_job_list); INIT_LIST_HEAD(&vc4->job_done_list); - INIT_LIST_HEAD(&vc4->seqno_cb_list); spin_lock_init(&vc4->job_lock); INIT_WORK(&vc4->hangcheck.reset_work, vc4_reset_work); diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index 5bf134968ade..1e7bdda55698 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -284,9 +284,6 @@ validate_indexed_prim_list(VALIDATE_ARGS) if (!ib) return -EINVAL; - exec->bin_dep_seqno = max(exec->bin_dep_seqno, - to_vc4_bo(&ib->base)->write_seqno); - if (offset > ib->base.size || (ib->base.size - offset) / index_size < length) { DRM_DEBUG("IB access overflow (%d + %d*%d > %zd)\n", @@ -738,11 +735,6 @@ reloc_tex(struct vc4_exec_info *exec, *validated_p0 = tex->dma_addr + p0; - if (is_cs) { - exec->bin_dep_seqno = max(exec->bin_dep_seqno, - to_vc4_bo(&tex->base)->write_seqno); - } - return true; fail: DRM_INFO("Texture p0 at %d: 0x%08x\n", sample->p_offset[0], p0); @@ -904,9 +896,6 @@ validate_gl_shader_rec(struct drm_device *dev, uint32_t stride = *(uint8_t *)(pkt_u + o + 5); uint32_t max_index; - exec->bin_dep_seqno = max(exec->bin_dep_seqno, - to_vc4_bo(&vbo->base)->write_seqno); - if (state->addr & 0x8) stride |= (*(uint32_t *)(pkt_u + 100 + i * 4)) & ~0xff; -- cgit v1.2.3-59-g8ed1b From 51678bb9a7fb25e44f38a4f0b1bd283fec809917 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 13 Jan 2025 10:33:40 +0000 Subject: drm/sched: Add helper to check job dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lets isolate scheduler internals from drivers such as pvr which currently walks the dependency array to look for fences. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Reviewed-by: Matt Coster Acked-by: Danilo Krummrich Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250113103341.43914-1-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/scheduler/sched_main.c | 23 +++++++++++++++++++++++ include/drm/gpu_scheduler.h | 3 ++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index d172e3158880..a48be16ab84f 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -984,6 +984,29 @@ int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job, } EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies); +/** + * drm_sched_job_has_dependency - check whether fence is the job's dependency + * @job: scheduler job to check + * @fence: fence to look for + * + * Returns: + * True if @fence is found within the job's dependencies, or otherwise false. + */ +bool drm_sched_job_has_dependency(struct drm_sched_job *job, + struct dma_fence *fence) +{ + struct dma_fence *f; + unsigned long index; + + xa_for_each(&job->dependencies, index, f) { + if (f == fence) + return true; + } + + return false; +} +EXPORT_SYMBOL(drm_sched_job_has_dependency); + /** * drm_sched_job_cleanup - clean up scheduler job resources * @job: scheduler job to clean up diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index e2e6af8849c6..a0ff08123f07 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -564,7 +564,8 @@ int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job, int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job, struct drm_gem_object *obj, bool write); - +bool drm_sched_job_has_dependency(struct drm_sched_job *job, + struct dma_fence *fence); void drm_sched_entity_modify_sched(struct drm_sched_entity *entity, struct drm_gpu_scheduler **sched_list, -- cgit v1.2.3-59-g8ed1b From cdb73451bc675392c9c76779e2fec720edafd7ab Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 13 Jan 2025 10:33:41 +0000 Subject: drm/imagination: Use the drm_sched_job_has_dependency helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of manually peeking into the DRM scheduler implementation details lets use the previously added helper. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Cc: Frank Binns Cc: Matt Coster Reviewed-by: Matt Coster Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250113103341.43914-2-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/imagination/pvr_job.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imagination/pvr_job.c b/drivers/gpu/drm/imagination/pvr_job.c index 618503a212a7..1cdb3cfd058d 100644 --- a/drivers/gpu/drm/imagination/pvr_job.c +++ b/drivers/gpu/drm/imagination/pvr_job.c @@ -597,8 +597,6 @@ update_job_resvs_for_each(struct pvr_job_data *job_data, u32 job_count) static bool can_combine_jobs(struct pvr_job *a, struct pvr_job *b) { struct pvr_job *geom_job = a, *frag_job = b; - struct dma_fence *fence; - unsigned long index; /* Geometry and fragment jobs can be combined if they are queued to the * same context and targeting the same HWRT. @@ -609,13 +607,9 @@ static bool can_combine_jobs(struct pvr_job *a, struct pvr_job *b) a->hwrt != b->hwrt) return false; - xa_for_each(&frag_job->base.dependencies, index, fence) { - /* We combine when we see an explicit geom -> frag dep. */ - if (&geom_job->base.s_fence->scheduled == fence) - return true; - } - - return false; + /* We combine when we see an explicit geom -> frag dep. */ + return drm_sched_job_has_dependency(&frag_job->base, + &geom_job->base.s_fence->scheduled); } static struct dma_fence * -- cgit v1.2.3-59-g8ed1b From 38f039f45964425d0d345e930ec1de53ab9b9c74 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:21:59 +0300 Subject: drm/i915: Allow async flips with render compression on TGL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like CCS + async flips has been a thing for a while now. Enable this for TGL+ render compression modifiers. Note that we can't update AUX_DIST during async flips we must check to make sure it remains unchanged. We also can't do clear color. Supposedly there was some attempt to make it work, but apparently the issues only got ironed out in MTL. For now we'll not worry about it and refuse async flips with clear color modifiers. Bspec claims that media compression doesn't support async flips. Based on a quick test it does seem to work to some degree, but perhaps it has issues as well. Let's trust the spec here and continue to refuse async flips + media compression. Bspec: 49250,49251,49252,49253 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-2-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/intel_display.c | 14 +++++++++++++- drivers/gpu/drm/i915/display/skl_universal_plane.c | 17 ++++++++++------- drivers/gpu/drm/i915/display/skl_universal_plane.h | 3 +++ 3 files changed, 26 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f5d2eacce119..9c2db307a660 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6554,6 +6554,9 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: case I915_FORMAT_MOD_4_TILED: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: + case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: case I915_FORMAT_MOD_4_TILED_BMG_CCS: case I915_FORMAT_MOD_4_TILED_LNL_CCS: break; @@ -6565,7 +6568,8 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in return -EINVAL; } - if (new_plane_state->hw.fb->format->num_planes > 1) { + if (intel_format_info_is_yuv_semiplanar(new_plane_state->hw.fb->format, + new_plane_state->hw.fb->modifier)) { drm_dbg_kms(&i915->drm, "[PLANE:%d:%s] Planar formats do not support async flips\n", plane->base.base.id, plane->base.name); @@ -6611,6 +6615,14 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in return -EINVAL; } + if (skl_plane_aux_dist(old_plane_state, 0) != + skl_plane_aux_dist(new_plane_state, 0)) { + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] AUX_DIST cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); + return -EINVAL; + } + if (!drm_rect_equals(&old_plane_state->uapi.src, &new_plane_state->uapi.src) || !drm_rect_equals(&old_plane_state->uapi.dst, &new_plane_state->uapi.dst)) { drm_dbg_kms(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index ff9764cac1e7..00ee7dfdeb5b 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -541,15 +541,18 @@ static u32 tgl_plane_min_alignment(struct intel_plane *plane, if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915)) return mult * 16 * 1024; return mult * 4 * 1024; - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: - case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: - case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: - case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: + if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915)) + return mult * 16 * 1024; + fallthrough; + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: + case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: case I915_FORMAT_MOD_4_TILED_BMG_CCS: case I915_FORMAT_MOD_4_TILED_LNL_CCS: /* @@ -1229,8 +1232,8 @@ static u32 skl_plane_surf(const struct intel_plane_state *plane_state, return plane_surf; } -static u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state, - int color_plane) +u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state, + int color_plane) { struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.h b/drivers/gpu/drm/i915/display/skl_universal_plane.h index 541489479135..18b41d13f0bd 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.h +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.h @@ -37,4 +37,7 @@ bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, u8 icl_hdr_plane_mask(void); bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id); +u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state, + int color_plane); + #endif -- cgit v1.2.3-59-g8ed1b From e2bd89d1aec61bf70a99731333cedae0881447b5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:22:00 +0300 Subject: drm/i915: Allow async flips with compression on ICL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently ICL can do async flips with CCS. In fact it already seems to work on GLK, but apparently can lead to underruns there so we'll only enable it for ICL. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-3-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/intel_display.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9c2db307a660..210d52dc33fc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6549,7 +6549,26 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in return -EINVAL; } break; - + case I915_FORMAT_MOD_Y_TILED_CCS: + case I915_FORMAT_MOD_Yf_TILED_CCS: + /* + * Display WA #0731: skl + * WaDisableRCWithAsyncFlip: skl + * "When render decompression is enabled, hardware + * internally converts the Async flips to Sync flips." + * + * Display WA #1159: glk + * "Async flip with render compression may result in + * intermittent underrun corruption." + */ + if (DISPLAY_VER(i915) < 11) { + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] Modifier 0x%llx does not support async flip on display ver %d\n", + plane->base.base.id, plane->base.name, + new_plane_state->hw.fb->modifier, DISPLAY_VER(i915)); + return -EINVAL; + } + break; case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: -- cgit v1.2.3-59-g8ed1b From 7cc1e19703a553eda5f463cbe1fb011877ad16c2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:22:01 +0300 Subject: drm/i915: Introduce plane->can_async_flip() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the "does this modifier support async flips?" check to be handled by the platform specific plane code instead of having a big mess in common code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-4-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/i9xx_plane.c | 9 +++ drivers/gpu/drm/i915/display/intel_atomic_plane.c | 5 ++ drivers/gpu/drm/i915/display/intel_atomic_plane.h | 1 + drivers/gpu/drm/i915/display/intel_display.c | 53 +------------- drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/skl_universal_plane.c | 80 ++++++++++++++++++++++ 6 files changed, 97 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 48e657a80a16..c46277e0d67d 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -673,6 +673,11 @@ vlv_primary_disable_flip_done(struct intel_plane *plane) spin_unlock_irq(&i915->irq_lock); } +static bool i9xx_plane_can_async_flip(u64 modifier) +{ + return modifier == I915_FORMAT_MOD_X_TILED; +} + static bool i9xx_plane_get_hw_state(struct intel_plane *plane, enum pipe *pipe) { @@ -959,19 +964,23 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->async_flip = vlv_primary_async_flip; plane->enable_flip_done = vlv_primary_enable_flip_done; plane->disable_flip_done = vlv_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; } else if (IS_BROADWELL(dev_priv)) { plane->need_async_flip_toggle_wa = true; plane->async_flip = g4x_primary_async_flip; plane->enable_flip_done = bdw_primary_enable_flip_done; plane->disable_flip_done = bdw_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; } else if (DISPLAY_VER(dev_priv) >= 7) { plane->async_flip = g4x_primary_async_flip; plane->enable_flip_done = ivb_primary_enable_flip_done; plane->disable_flip_done = ivb_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; } else if (DISPLAY_VER(dev_priv) >= 5) { plane->async_flip = g4x_primary_async_flip; plane->enable_flip_done = ilk_primary_enable_flip_done; plane->disable_flip_done = ilk_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; } modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X); diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 612e9b0ec14a..5e0e07496867 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -156,6 +156,11 @@ bool intel_plane_needs_physical(struct intel_plane *plane) DISPLAY_INFO(i915)->cursor_needs_physical; } +bool intel_plane_can_async_flip(struct intel_plane *plane, u64 modifier) +{ + return plane->can_async_flip && plane->can_async_flip(modifier); +} + unsigned int intel_adjusted_rate(const struct drm_rect *src, const struct drm_rect *dst, unsigned int rate) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 0f982f452ff3..fb87b3353ab0 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -19,6 +19,7 @@ struct intel_plane; struct intel_plane_state; enum plane_id; +bool intel_plane_can_async_flip(struct intel_plane *plane, u64 modifier); unsigned int intel_adjusted_rate(const struct drm_rect *src, const struct drm_rect *dst, unsigned int rate); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 210d52dc33fc..5ae0dea7b245 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6528,58 +6528,7 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in if (!plane->async_flip) continue; - /* - * FIXME: This check is kept generic for all platforms. - * Need to verify this for all gen9 platforms to enable - * this selectively if required. - */ - switch (new_plane_state->hw.fb->modifier) { - case DRM_FORMAT_MOD_LINEAR: - /* - * FIXME: Async on Linear buffer is supported on ICL as - * but with additional alignment and fbc restrictions - * need to be taken care of. These aren't applicable for - * gen12+. - */ - if (DISPLAY_VER(i915) < 12) { - drm_dbg_kms(&i915->drm, - "[PLANE:%d:%s] Modifier 0x%llx does not support async flip on display ver %d\n", - plane->base.base.id, plane->base.name, - new_plane_state->hw.fb->modifier, DISPLAY_VER(i915)); - return -EINVAL; - } - break; - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Yf_TILED_CCS: - /* - * Display WA #0731: skl - * WaDisableRCWithAsyncFlip: skl - * "When render decompression is enabled, hardware - * internally converts the Async flips to Sync flips." - * - * Display WA #1159: glk - * "Async flip with render compression may result in - * intermittent underrun corruption." - */ - if (DISPLAY_VER(i915) < 11) { - drm_dbg_kms(&i915->drm, - "[PLANE:%d:%s] Modifier 0x%llx does not support async flip on display ver %d\n", - plane->base.base.id, plane->base.name, - new_plane_state->hw.fb->modifier, DISPLAY_VER(i915)); - return -EINVAL; - } - break; - case I915_FORMAT_MOD_X_TILED: - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Yf_TILED: - case I915_FORMAT_MOD_4_TILED: - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: - case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: - case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: - case I915_FORMAT_MOD_4_TILED_BMG_CCS: - case I915_FORMAT_MOD_4_TILED_LNL_CCS: - break; - default: + if (!intel_plane_can_async_flip(plane, new_plane_state->hw.fb->modifier)) { drm_dbg_kms(&i915->drm, "[PLANE:%d:%s] Modifier 0x%llx does not support async flip\n", plane->base.base.id, plane->base.name, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 8271e50e3644..083eb86f0904 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1474,6 +1474,7 @@ struct intel_plane { unsigned int (*max_stride)(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); + bool (*can_async_flip)(u64 modifier); /* Write all non-self arming plane registers */ void (*update_noarm)(struct intel_dsb *dsb, struct intel_plane *plane, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 00ee7dfdeb5b..2679b446ab2b 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -516,6 +516,79 @@ skl_plane_max_stride(struct intel_plane *plane, max_pixels, max_bytes); } +static bool tgl_plane_can_async_flip(u64 modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + case I915_FORMAT_MOD_X_TILED: + case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_4_TILED: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: + case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: + case I915_FORMAT_MOD_4_TILED_BMG_CCS: + case I915_FORMAT_MOD_4_TILED_LNL_CCS: + return true; + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: + case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: + case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: + return false; + default: + return false; + } +} + +static bool icl_plane_can_async_flip(u64 modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + /* + * FIXME: Async on Linear buffer is supported on ICL + * but with additional alignment and fbc restrictions + * need to be taken care of. + */ + return false; + case I915_FORMAT_MOD_X_TILED: + case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_Yf_TILED: + case I915_FORMAT_MOD_Y_TILED_CCS: + case I915_FORMAT_MOD_Yf_TILED_CCS: + return true; + default: + return false; + } +} + +static bool skl_plane_can_async_flip(u64 modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + return false; + case I915_FORMAT_MOD_X_TILED: + case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_Yf_TILED: + return true; + case I915_FORMAT_MOD_Y_TILED_CCS: + case I915_FORMAT_MOD_Yf_TILED_CCS: + /* + * Display WA #0731: skl + * WaDisableRCWithAsyncFlip: skl + * "When render decompression is enabled, hardware + * internally converts the Async flips to Sync flips." + * + * Display WA #1159: glk + * "Async flip with render compression may result in + * intermittent underrun corruption." + */ + return false; + default: + return false; + } +} + static u32 tgl_plane_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) @@ -2679,6 +2752,13 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->async_flip = skl_plane_async_flip; plane->enable_flip_done = skl_plane_enable_flip_done; plane->disable_flip_done = skl_plane_disable_flip_done; + + if (DISPLAY_VER(dev_priv) >= 12) + plane->can_async_flip = tgl_plane_can_async_flip; + else if (DISPLAY_VER(dev_priv) == 11) + plane->can_async_flip = icl_plane_can_async_flip; + else + plane->can_async_flip = skl_plane_can_async_flip; } if (DISPLAY_VER(dev_priv) >= 11) -- cgit v1.2.3-59-g8ed1b From 2f4c92166ed53d46b4ad66b7cffb1350dec8c0b6 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:22:02 +0300 Subject: drm/i915: Use plane->can_async_flip() for alignment exceptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Async flips often require bigger alignment that sync flips. Currently we have HAS_ASYNC_FLIPS() checks strewn about to inidcate that async flips are generally supported and thus we want more alignment. Switch that over to using intel_plane_can_async_flip() so that we can handle these in a slightly less messy way. Currently we don't have cases where async flips would require different alignment for different modifiers on the same plane. We'll also move the HAS_ASYNC_FLIPS() check to the plane init code so that we can still use that as a quick way to disable the async flips workarounds for testing purposes. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-5-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/i9xx_plane.c | 55 +++++++++++----------- drivers/gpu/drm/i915/display/skl_universal_plane.c | 21 ++++----- 2 files changed, 37 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index c46277e0d67d..d05a12434f01 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -780,12 +780,11 @@ static unsigned int vlv_primary_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) { - struct drm_i915_private *i915 = to_i915(plane->base.dev); + if (intel_plane_can_async_flip(plane, fb->modifier)) + return 256 * 1024; switch (fb->modifier) { case I915_FORMAT_MOD_X_TILED: - if (HAS_ASYNC_FLIPS(i915)) - return 256 * 1024; return 4 * 1024; case DRM_FORMAT_MOD_LINEAR: return 128 * 1024; @@ -799,13 +798,11 @@ static unsigned int g4x_primary_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) { - struct drm_i915_private *i915 = to_i915(plane->base.dev); + if (intel_plane_can_async_flip(plane, fb->modifier)) + return 256 * 1024; switch (fb->modifier) { case I915_FORMAT_MOD_X_TILED: - if (HAS_ASYNC_FLIPS(i915)) - return 256 * 1024; - return 4 * 1024; case DRM_FORMAT_MOD_LINEAR: return 4 * 1024; default: @@ -960,27 +957,29 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->get_hw_state = i9xx_plane_get_hw_state; plane->check_plane = i9xx_plane_check; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - plane->async_flip = vlv_primary_async_flip; - plane->enable_flip_done = vlv_primary_enable_flip_done; - plane->disable_flip_done = vlv_primary_disable_flip_done; - plane->can_async_flip = i9xx_plane_can_async_flip; - } else if (IS_BROADWELL(dev_priv)) { - plane->need_async_flip_toggle_wa = true; - plane->async_flip = g4x_primary_async_flip; - plane->enable_flip_done = bdw_primary_enable_flip_done; - plane->disable_flip_done = bdw_primary_disable_flip_done; - plane->can_async_flip = i9xx_plane_can_async_flip; - } else if (DISPLAY_VER(dev_priv) >= 7) { - plane->async_flip = g4x_primary_async_flip; - plane->enable_flip_done = ivb_primary_enable_flip_done; - plane->disable_flip_done = ivb_primary_disable_flip_done; - plane->can_async_flip = i9xx_plane_can_async_flip; - } else if (DISPLAY_VER(dev_priv) >= 5) { - plane->async_flip = g4x_primary_async_flip; - plane->enable_flip_done = ilk_primary_enable_flip_done; - plane->disable_flip_done = ilk_primary_disable_flip_done; - plane->can_async_flip = i9xx_plane_can_async_flip; + if (HAS_ASYNC_FLIPS(dev_priv)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + plane->async_flip = vlv_primary_async_flip; + plane->enable_flip_done = vlv_primary_enable_flip_done; + plane->disable_flip_done = vlv_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } else if (IS_BROADWELL(dev_priv)) { + plane->need_async_flip_toggle_wa = true; + plane->async_flip = g4x_primary_async_flip; + plane->enable_flip_done = bdw_primary_enable_flip_done; + plane->disable_flip_done = bdw_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } else if (DISPLAY_VER(dev_priv) >= 7) { + plane->async_flip = g4x_primary_async_flip; + plane->enable_flip_done = ivb_primary_enable_flip_done; + plane->disable_flip_done = ivb_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } else if (DISPLAY_VER(dev_priv) >= 5) { + plane->async_flip = g4x_primary_async_flip; + plane->enable_flip_done = ilk_primary_enable_flip_done; + plane->disable_flip_done = ilk_primary_disable_flip_done; + plane->can_async_flip = i9xx_plane_can_async_flip; + } } modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 2679b446ab2b..474522f64b41 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -601,25 +601,24 @@ static u32 tgl_plane_min_alignment(struct intel_plane *plane, if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return mult * 4 * 1024; + /* + * FIXME ADL sees GGTT/DMAR faults with async + * flips unless we align to 16k at least. + * Figure out what's going on here... + */ + if (IS_ALDERLAKE_P(i915) && + intel_plane_can_async_flip(plane, fb->modifier)) + return mult * 16 * 1024; + switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_4_TILED: - /* - * FIXME ADL sees GGTT/DMAR faults with async - * flips unless we align to 16k at least. - * Figure out what's going on here... - */ - if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915)) - return mult * 16 * 1024; return mult * 4 * 1024; case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: - if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915)) - return mult * 16 * 1024; - fallthrough; case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: @@ -2747,7 +2746,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->get_hw_state = skl_plane_get_hw_state; plane->check_plane = skl_plane_check; - if (plane_id == PLANE_1) { + if (HAS_ASYNC_FLIPS(dev_priv) && plane_id == PLANE_1) { plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(dev_priv, 9, 10); plane->async_flip = skl_plane_async_flip; plane->enable_flip_done = skl_plane_enable_flip_done; -- cgit v1.2.3-59-g8ed1b From d851663664a3515dc1272fc7ef35a6e0db467b31 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:22:03 +0300 Subject: drm/i915: Reuse vlv_primary_min_alignment() for sprites as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename vlv_primary_min_alignment() to vlv_plane_min_alignment() and use it to replace vlv_sprite_min_alignment() since the behaviour is now identical when the plane init doesn't set up any async flips stuff. Technically VLV/CHV sprites do support async flips, so this also makes us a bit more future proof if/when we extend async flip support to more than one plane. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-6-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/i9xx_plane.c | 8 ++++---- drivers/gpu/drm/i915/display/i9xx_plane.h | 4 ++++ drivers/gpu/drm/i915/display/intel_sprite.c | 17 +---------------- 3 files changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index d05a12434f01..ed171fbf8720 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -776,9 +776,9 @@ i8xx_plane_max_stride(struct intel_plane *plane, return 8 * 1024; } -static unsigned int vlv_primary_min_alignment(struct intel_plane *plane, - const struct drm_framebuffer *fb, - int color_plane) +unsigned int vlv_plane_min_alignment(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane) { if (intel_plane_can_async_flip(plane, fb->modifier)) return 256 * 1024; @@ -939,7 +939,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) } if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - plane->min_alignment = vlv_primary_min_alignment; + plane->min_alignment = vlv_plane_min_alignment; else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) plane->min_alignment = g4x_primary_min_alignment; else if (DISPLAY_VER(dev_priv) == 4) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.h b/drivers/gpu/drm/i915/display/i9xx_plane.h index 0ca12d1e6839..457f4bccf106 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.h +++ b/drivers/gpu/drm/i915/display/i9xx_plane.h @@ -9,6 +9,7 @@ #include enum pipe; +struct drm_framebuffer; struct drm_i915_private; struct intel_crtc; struct intel_initial_plane_config; @@ -19,6 +20,9 @@ struct intel_plane_state; unsigned int i965_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); +unsigned int vlv_plane_min_alignment(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int colot_plane); int i9xx_check_plane_surface(struct intel_plane_state *plane_state); struct intel_plane * diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index e6fadcef58e0..13996d7059ad 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -253,21 +253,6 @@ int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state, return DIV_ROUND_UP(pixel_rate * num, den); } -static unsigned int vlv_sprite_min_alignment(struct intel_plane *plane, - const struct drm_framebuffer *fb, - int color_plane) -{ - switch (fb->modifier) { - case I915_FORMAT_MOD_X_TILED: - return 4 * 1024; - case DRM_FORMAT_MOD_LINEAR: - return 128 * 1024; - default: - MISSING_CASE(fb->modifier); - return 0; - } -} - static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) { u32 sprctl = 0; @@ -1616,7 +1601,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->get_hw_state = vlv_sprite_get_hw_state; plane->check_plane = vlv_sprite_check; plane->max_stride = i965_plane_max_stride; - plane->min_alignment = vlv_sprite_min_alignment; + plane->min_alignment = vlv_plane_min_alignment; plane->min_cdclk = vlv_plane_min_cdclk; if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { -- cgit v1.2.3-59-g8ed1b From 8e1096fd03b6c0e3e668cc2e4f0edbdc7de8fa01 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:22:04 +0300 Subject: drm/i915: Disable scanout VT-d workaround for TGL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TGL+ should no longer need any VT-d scanout workarounds. Don't apply any. Not 100% sure whether pre-SNB might also suffer from this. The workaround did originate on SNB but who knows if it was just never caught before that. Not that I ever managed to enable VT-d any older hardware. Last time I tried on my ILK it ate the disk! Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-7-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5ae0dea7b245..15f298d0424a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8743,5 +8743,5 @@ void intel_hpd_poll_fini(struct drm_i915_private *i915) bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915) { - return DISPLAY_VER(i915) >= 6 && i915_vtd_active(i915); + return IS_DISPLAY_VER(i915, 6, 11) && i915_vtd_active(i915); } -- cgit v1.2.3-59-g8ed1b From e7dfd7c60e402e658238d25c8da4f8645e45b982 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:22:05 +0300 Subject: drm/i915: Nuke ADL pre-production Wa_22011186057 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wa_22011186057 (some CCS problem) only affected ADL A-stepping, which I presume is pre-production hw. Drop the dead code. Bspec: 54369 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-8-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 474522f64b41..4bede904e1b5 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2615,10 +2615,6 @@ skl_plane_disable_flip_done(struct intel_plane *plane) static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915, enum pipe pipe, enum plane_id plane_id) { - /* Wa_22011186057 */ - if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) - return false; - if (DISPLAY_VER(i915) >= 11) return true; @@ -2640,10 +2636,6 @@ static bool tgl_plane_has_mc_ccs(struct drm_i915_private *i915, (IS_TIGERLAKE(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_D0))) return false; - /* Wa_22011186057 */ - if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) - return false; - return plane_id < PLANE_6; } -- cgit v1.2.3-59-g8ed1b From 71ca4715151e033c16427b8cfaa9b5393dd6a010 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2024 21:22:06 +0300 Subject: drm/i915: Relocate xe AUX hack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the xe AUX neutering out from skl_get_plane_caps() into the caller so that it'll be easier to refactor skl_get_plane_caps() into a more readable shape. This isn't really hardware specific anyway, and just some kind of bug/misfeature of xe. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241009182207.22900-9-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 4bede904e1b5..aa8a38c0ca3c 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2652,9 +2652,6 @@ static u8 skl_get_plane_caps(struct drm_i915_private *i915, if (HAS_4TILE(display)) caps |= INTEL_PLANE_CAP_TILING_4; - if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(i915)) - return caps; - if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) { caps |= INTEL_PLANE_CAP_CCS_RC; if (DISPLAY_VER(display) >= 12) @@ -2683,6 +2680,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, const u32 *formats; int num_formats; int ret; + u8 caps; plane = intel_plane_alloc(); if (IS_ERR(plane)) @@ -2774,8 +2772,15 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, else plane_type = DRM_PLANE_TYPE_OVERLAY; - modifiers = intel_fb_plane_get_modifiers(dev_priv, - skl_get_plane_caps(dev_priv, pipe, plane_id)); + caps = skl_get_plane_caps(dev_priv, pipe, plane_id); + + /* FIXME: xe has problems with AUX */ + if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(dev_priv)) + caps &= ~(INTEL_PLANE_CAP_CCS_RC | + INTEL_PLANE_CAP_CCS_RC_CC | + INTEL_PLANE_CAP_CCS_MC); + + modifiers = intel_fb_plane_get_modifiers(dev_priv, caps); ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, -- cgit v1.2.3-59-g8ed1b From 6f7c813c88aed90ca342a76ef4cdc078d6210e07 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 10 Oct 2024 19:46:17 +0300 Subject: drm/i915: Carve up skl_get_plane_caps() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split skl_get_plane_caps() into four variants: skl_plane_caps(), glk_plane_caps(), icl_plane_caps(), tgl_plane_caps(). Makes it easier to figure out what is actually going on there. v2: skl_plane_caps() should return u8 not bool Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241010164617.10280-1-ville.syrjala@linux.intel.com Reviewed-by: Jouni Högander --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 81 +++++++++++++++------- 1 file changed, 57 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index aa8a38c0ca3c..450dd8c64e0c 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2615,48 +2615,74 @@ skl_plane_disable_flip_done(struct intel_plane *plane) static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915, enum pipe pipe, enum plane_id plane_id) { - if (DISPLAY_VER(i915) >= 11) - return true; - - if (IS_GEMINILAKE(i915)) - return pipe != PIPE_C; - return pipe != PIPE_C && (plane_id == PLANE_1 || plane_id == PLANE_2); } +static u8 skl_plane_caps(struct drm_i915_private *i915, + enum pipe pipe, enum plane_id plane_id) +{ + u8 caps = INTEL_PLANE_CAP_TILING_X | + INTEL_PLANE_CAP_TILING_Y | + INTEL_PLANE_CAP_TILING_Yf; + + if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) + caps |= INTEL_PLANE_CAP_CCS_RC; + + return caps; +} + +static bool glk_plane_has_rc_ccs(struct drm_i915_private *i915, + enum pipe pipe) +{ + return pipe != PIPE_C; +} + +static u8 glk_plane_caps(struct drm_i915_private *i915, + enum pipe pipe, enum plane_id plane_id) +{ + u8 caps = INTEL_PLANE_CAP_TILING_X | + INTEL_PLANE_CAP_TILING_Y | + INTEL_PLANE_CAP_TILING_Yf; + + if (glk_plane_has_rc_ccs(i915, pipe)) + caps |= INTEL_PLANE_CAP_CCS_RC; + + return caps; +} + +static u8 icl_plane_caps(struct drm_i915_private *i915, + enum pipe pipe, enum plane_id plane_id) +{ + return INTEL_PLANE_CAP_TILING_X | + INTEL_PLANE_CAP_TILING_Y | + INTEL_PLANE_CAP_TILING_Yf | + INTEL_PLANE_CAP_CCS_RC; +} + static bool tgl_plane_has_mc_ccs(struct drm_i915_private *i915, enum plane_id plane_id) { - if (DISPLAY_VER(i915) < 12) - return false; - /* Wa_14010477008 */ if (IS_DG1(i915) || IS_ROCKETLAKE(i915) || - (IS_TIGERLAKE(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_D0))) + (IS_TIGERLAKE(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_D0))) return false; return plane_id < PLANE_6; } -static u8 skl_get_plane_caps(struct drm_i915_private *i915, - enum pipe pipe, enum plane_id plane_id) +static u8 tgl_plane_caps(struct drm_i915_private *i915, + enum pipe pipe, enum plane_id plane_id) { struct intel_display *display = &i915->display; - u8 caps = INTEL_PLANE_CAP_TILING_X; + u8 caps = INTEL_PLANE_CAP_TILING_X | + INTEL_PLANE_CAP_CCS_RC | + INTEL_PLANE_CAP_CCS_RC_CC; - if (DISPLAY_VER(display) < 13 || display->platform.alderlake_p) - caps |= INTEL_PLANE_CAP_TILING_Y; - if (DISPLAY_VER(display) < 12) - caps |= INTEL_PLANE_CAP_TILING_Yf; if (HAS_4TILE(display)) caps |= INTEL_PLANE_CAP_TILING_4; - - if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) { - caps |= INTEL_PLANE_CAP_CCS_RC; - if (DISPLAY_VER(display) >= 12) - caps |= INTEL_PLANE_CAP_CCS_RC_CC; - } + else + caps |= INTEL_PLANE_CAP_TILING_Y; if (tgl_plane_has_mc_ccs(i915, plane_id)) caps |= INTEL_PLANE_CAP_CCS_MC; @@ -2772,7 +2798,14 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, else plane_type = DRM_PLANE_TYPE_OVERLAY; - caps = skl_get_plane_caps(dev_priv, pipe, plane_id); + if (DISPLAY_VER(dev_priv) >= 12) + caps = tgl_plane_caps(dev_priv, pipe, plane_id); + else if (DISPLAY_VER(dev_priv) == 11) + caps = icl_plane_caps(dev_priv, pipe, plane_id); + else if (DISPLAY_VER(dev_priv) == 10) + caps = glk_plane_caps(dev_priv, pipe, plane_id); + else + caps = skl_plane_caps(dev_priv, pipe, plane_id); /* FIXME: xe has problems with AUX */ if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(dev_priv)) -- cgit v1.2.3-59-g8ed1b From 2499212e21601740ed7d5563563f39cf7e7d833a Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Fri, 17 Jan 2025 09:42:48 +0530 Subject: drm/i915/hdcp: Use correct function to check if encoder is HDMI Use intel_encoder_is_hdmi function which was recently introduced to see if encoder is HDMI or not. --v2 -Add Fixes tag [Jani] Fixes: 6a3691ca4799 ("drm/i915/hdcp: Disable HDCP Line Rekeying for HDCP2.2 on HDMI") Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20250117041247.1084381-1-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index c60b22aaa819..1bab7c34a794 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -41,7 +41,7 @@ intel_hdcp_adjust_hdcp_line_rekeying(struct intel_encoder *encoder, u32 rekey_bit = 0; /* Here we assume HDMI is in TMDS mode of operation */ - if (encoder->type != INTEL_OUTPUT_HDMI) + if (!intel_encoder_is_hdmi(encoder)) return; if (DISPLAY_VER(display) >= 30) { -- cgit v1.2.3-59-g8ed1b From 67a98f7e27baf8c22483ec4873a8d8efdf71b55d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Fri, 6 Dec 2024 19:20:32 +0100 Subject: drm/xe/display: Re-use display vmas when possible i915 has this really nice, infrastructure where everything becomes complicated, GGTT needs eviction, etc.. Lets not do that, and make the dumbest possible interface instead. Try to retrieve the VMA from old_plane_state, or intel_fbdev if kernel fb. Link: https://patchwork.freedesktop.org/patch/msgid/20241206182032.196307-1-dev@lankhorst.se Signed-off-by: Maarten Lankhorst Reviewed-by: Animesh Manna Tested-by: Jani Saarinen --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 2 +- drivers/gpu/drm/i915/display/intel_cursor.c | 2 +- drivers/gpu/drm/i915/display/intel_fb_pin.c | 3 +- drivers/gpu/drm/i915/display/intel_fb_pin.h | 3 +- drivers/gpu/drm/i915/display/intel_fbdev.c | 5 +++ drivers/gpu/drm/i915/display/intel_fbdev.h | 8 ++++ drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h | 3 ++ drivers/gpu/drm/xe/display/xe_fb_pin.c | 48 ++++++++++++++++++++--- 8 files changed, 65 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 5e0e07496867..c558143f4f82 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -1135,7 +1135,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane, if (!obj) return 0; - ret = intel_plane_pin_fb(new_plane_state); + ret = intel_plane_pin_fb(new_plane_state, old_plane_state); 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 57cf8f46a458..ae7243ad6e0c 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -865,7 +865,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane, if (ret) goto out_free; - ret = intel_plane_pin_fb(new_plane_state); + ret = intel_plane_pin_fb(new_plane_state, old_plane_state); if (ret) goto out_free; diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c index d3a86f9c6bc8..dd3ac7f98dfc 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -252,7 +252,8 @@ intel_plane_fb_min_phys_alignment(const struct intel_plane_state *plane_state) return plane->min_alignment(plane, fb, 0); } -int intel_plane_pin_fb(struct intel_plane_state *plane_state) +int intel_plane_pin_fb(struct intel_plane_state *plane_state, + const struct intel_plane_state *old_plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct intel_framebuffer *fb = diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index ac0319b53af0..0fc6d9044638 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -23,7 +23,8 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags); -int intel_plane_pin_fb(struct intel_plane_state *plane_state); +int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, + const struct intel_plane_state *old_plane_state); void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state); #endif diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 00852ff5b247..6c0808133397 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -695,3 +695,8 @@ struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev) return to_intel_framebuffer(fbdev->helper.fb); } + +struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev) +{ + return fbdev ? fbdev->vma : NULL; +} diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.h b/drivers/gpu/drm/i915/display/intel_fbdev.h index 08de2d5b3433..24a3434558cb 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.h +++ b/drivers/gpu/drm/i915/display/intel_fbdev.h @@ -17,6 +17,8 @@ struct intel_framebuffer; void intel_fbdev_setup(struct drm_i915_private *dev_priv); void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous); struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev); +struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev); + #else static inline void intel_fbdev_setup(struct drm_i915_private *dev_priv) { @@ -30,6 +32,12 @@ static inline struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbd { return NULL; } + +static inline struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev) +{ + return NULL; +} + #endif #endif /* __INTEL_FBDEV_H__ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h index bdae8392e125..4465c40f8134 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h @@ -10,6 +10,8 @@ #include "xe_ggtt_types.h" +#include + /* We don't want these from i915_drm.h in case of Xe */ #undef I915_TILING_X #undef I915_TILING_Y @@ -19,6 +21,7 @@ struct xe_bo; struct i915_vma { + refcount_t ref; struct xe_bo *bo, *dpt; struct xe_ggtt_node *node; }; diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 9fa51b84737c..25ce032bb293 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -9,6 +9,7 @@ #include "intel_dpt.h" #include "intel_fb.h" #include "intel_fb_pin.h" +#include "intel_fbdev.h" #include "xe_bo.h" #include "xe_device.h" #include "xe_ggtt.h" @@ -287,6 +288,7 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, if (!vma) return ERR_PTR(-ENODEV); + refcount_set(&vma->ref, 1); if (IS_DGFX(to_xe_device(bo->ttm.base.dev)) && intel_fb_rc_ccs_cc_plane(&fb->base) >= 0 && !(bo->flags & XE_BO_FLAG_NEEDS_CPU_ACCESS)) { @@ -347,6 +349,9 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma) { u8 tile_id = vma->node->ggtt->tile->id; + if (!refcount_dec_and_test(&vma->ref)) + return; + if (vma->dpt) xe_bo_unpin_map_no_vm(vma->dpt); else if (!xe_ggtt_node_allocated(vma->bo->ggtt_node[tile_id]) || @@ -377,25 +382,58 @@ void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags) __xe_unpin_fb_vma(vma); } -int intel_plane_pin_fb(struct intel_plane_state *plane_state) +static bool reuse_vma(struct intel_plane_state *new_plane_state, + const struct intel_plane_state *old_plane_state) { - struct drm_framebuffer *fb = plane_state->hw.fb; + struct intel_framebuffer *fb = to_intel_framebuffer(new_plane_state->hw.fb); + struct xe_device *xe = to_xe_device(fb->base.dev); + struct i915_vma *vma; + + if (old_plane_state->hw.fb == new_plane_state->hw.fb && + !memcmp(&old_plane_state->view.gtt, + &new_plane_state->view.gtt, + sizeof(new_plane_state->view.gtt))) { + vma = old_plane_state->ggtt_vma; + goto found; + } + + if (fb == intel_fbdev_framebuffer(xe->display.fbdev.fbdev)) { + vma = intel_fbdev_vma_pointer(xe->display.fbdev.fbdev); + if (vma) + goto found; + } + + return false; + +found: + refcount_inc(&vma->ref); + new_plane_state->ggtt_vma = vma; + return true; +} + +int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, + const struct intel_plane_state *old_plane_state) +{ + struct drm_framebuffer *fb = new_plane_state->hw.fb; struct drm_gem_object *obj = intel_fb_bo(fb); struct xe_bo *bo = gem_to_xe_bo(obj); struct i915_vma *vma; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); u64 phys_alignment = plane->min_alignment(plane, fb, 0); + if (reuse_vma(new_plane_state, old_plane_state)) + return 0; + /* We reject creating !SCANOUT fb's, so this is weird.. */ drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_SCANOUT)); - vma = __xe_pin_fb_vma(intel_fb, &plane_state->view.gtt, phys_alignment); + vma = __xe_pin_fb_vma(intel_fb, &new_plane_state->view.gtt, phys_alignment); if (IS_ERR(vma)) return PTR_ERR(vma); - plane_state->ggtt_vma = vma; + new_plane_state->ggtt_vma = vma; return 0; } -- cgit v1.2.3-59-g8ed1b From 0a3f3f7c5da8e45e1d4adf4ed6f4e2b05912785a Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:13 +0100 Subject: drm/vkms: Switch to managed for connector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current VKMS driver uses non-managed function to create connectors. It is not an issue yet, but in order to support multiple devices easily, convert this code to use drm and device managed helpers. Reviewed-by: Maxime Ripard Reviewed-by: Maíra Canal Reviewed-by: Thomas Zimmermann Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-1-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_output.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 8f4bd5aef087..570823ecb28f 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -3,11 +3,11 @@ #include "vkms_drv.h" #include #include +#include #include static const struct drm_connector_funcs vkms_connector_funcs = { .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, @@ -75,8 +75,8 @@ int vkms_output_init(struct vkms_device *vkmsdev) } } - ret = drm_connector_init(dev, connector, &vkms_connector_funcs, - DRM_MODE_CONNECTOR_VIRTUAL); + ret = drmm_connector_init(dev, connector, &vkms_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL, NULL); if (ret) { DRM_ERROR("Failed to init connector\n"); return ret; @@ -88,7 +88,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) DRM_MODE_ENCODER_VIRTUAL, NULL); if (ret) { DRM_ERROR("Failed to init encoder\n"); - goto err_encoder; + return ret; } encoder->possible_crtcs = drm_crtc_mask(crtc); @@ -110,9 +110,5 @@ int vkms_output_init(struct vkms_device *vkmsdev) err_attach: drm_encoder_cleanup(encoder); - -err_encoder: - drm_connector_cleanup(connector); - return ret; } -- cgit v1.2.3-59-g8ed1b From 16d22ba2debda22907b3eda4cc8ec1229136f424 Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:14 +0100 Subject: drm/vkms: Switch to managed for encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current VKMS driver uses non-managed function to create encoders. It is not an issue yet, but in order to support multiple devices easily, convert this code to use drm and device managed helpers. Reviewed-by: Maxime Ripard Reviewed-by: Maíra Canal Reviewed-by: Thomas Zimmermann Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-2-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_output.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 570823ecb28f..ab9affa75b66 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -13,10 +13,6 @@ static const struct drm_connector_funcs vkms_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static const struct drm_encoder_funcs vkms_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - static int vkms_conn_get_modes(struct drm_connector *connector) { int count; @@ -84,8 +80,8 @@ int vkms_output_init(struct vkms_device *vkmsdev) drm_connector_helper_add(connector, &vkms_conn_helper_funcs); - ret = drm_encoder_init(dev, encoder, &vkms_encoder_funcs, - DRM_MODE_ENCODER_VIRTUAL, NULL); + ret = drmm_encoder_init(dev, encoder, NULL, + DRM_MODE_ENCODER_VIRTUAL, NULL); if (ret) { DRM_ERROR("Failed to init encoder\n"); return ret; @@ -95,7 +91,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) ret = drm_connector_attach_encoder(connector, encoder); if (ret) { DRM_ERROR("Failed to attach connector to encoder\n"); - goto err_attach; + return ret; } if (vkmsdev->config->writeback) { @@ -108,7 +104,5 @@ int vkms_output_init(struct vkms_device *vkmsdev) return 0; -err_attach: - drm_encoder_cleanup(encoder); return ret; } -- cgit v1.2.3-59-g8ed1b From c367b772e6d89d8c7b560c7df7e3803ce6b8bcea Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:15 +0100 Subject: drm/managed: Add DRM-managed alloc_ordered_workqueue Add drmm_alloc_ordered_workqueue(), a helper that provides managed ordered workqueue cleanup. The workqueue will be destroyed with the final reference of the DRM device. Reviewed-by: Thomas Zimmermann Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-3-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/drm_managed.c | 8 ++++++++ include/drm/drm_managed.h | 12 ++++++++++++ 2 files changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index 79ce86a5bd67..cc4c463daae7 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -310,3 +310,11 @@ void __drmm_mutex_release(struct drm_device *dev, void *res) mutex_destroy(lock); } EXPORT_SYMBOL(__drmm_mutex_release); + +void __drmm_workqueue_release(struct drm_device *device, void *res) +{ + struct workqueue_struct *wq = res; + + destroy_workqueue(wq); +} +EXPORT_SYMBOL(__drmm_workqueue_release); diff --git a/include/drm/drm_managed.h b/include/drm/drm_managed.h index f547b09ca023..53017cc609ac 100644 --- a/include/drm/drm_managed.h +++ b/include/drm/drm_managed.h @@ -127,4 +127,16 @@ void __drmm_mutex_release(struct drm_device *dev, void *res); drmm_add_action_or_reset(dev, __drmm_mutex_release, lock); \ }) \ +void __drmm_workqueue_release(struct drm_device *device, void *wq); + +#define drmm_alloc_ordered_workqueue(dev, fmt, flags, args...) \ + ({ \ + struct workqueue_struct *wq = alloc_ordered_workqueue(fmt, flags, ##args); \ + wq ? ({ \ + int ret = drmm_add_action_or_reset(dev, __drmm_workqueue_release, wq); \ + ret ? ERR_PTR(ret) : wq; \ + }) : \ + wq; \ + }) + #endif -- cgit v1.2.3-59-g8ed1b From 8dd92e6eee590179818ba155cf02dc172e0c88c9 Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:16 +0100 Subject: drm/vkms: Switch to managed for crtc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current VKMS driver uses managed function to create crtc, but don't use it to properly clean the crtc workqueue. It is not an issue yet, but in order to support multiple devices easily, convert this code to use drm and device managed helpers. Acked-by: Maxime Ripard Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-4-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_crtc.c | 5 ++++- drivers/gpu/drm/vkms/vkms_drv.c | 9 --------- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 28a57ae109fc..434c35d5e947 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -296,7 +297,9 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, spin_lock_init(&vkms_out->lock); spin_lock_init(&vkms_out->composer_lock); - vkms_out->composer_workq = alloc_ordered_workqueue("vkms_composer", 0); + vkms_out->composer_workq = drmm_alloc_ordered_workqueue(dev, "vkms_composer", 0); + if (IS_ERR(vkms_out->composer_workq)) + return PTR_ERR(vkms_out->composer_workq); if (!vkms_out->composer_workq) return -ENOMEM; diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index e0409aba9349..7c142bfc3bd9 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -53,14 +53,6 @@ MODULE_PARM_DESC(enable_overlay, "Enable/Disable overlay support"); DEFINE_DRM_GEM_FOPS(vkms_driver_fops); -static void vkms_release(struct drm_device *dev) -{ - struct vkms_device *vkms = drm_device_to_vkms_device(dev); - - if (vkms->output.composer_workq) - destroy_workqueue(vkms->output.composer_workq); -} - static void vkms_atomic_commit_tail(struct drm_atomic_state *old_state) { struct drm_device *dev = old_state->dev; @@ -108,7 +100,6 @@ static const struct drm_debugfs_info vkms_config_debugfs_list[] = { static const struct drm_driver vkms_driver = { .driver_features = DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM, - .release = vkms_release, .fops = &vkms_driver_fops, DRM_GEM_SHMEM_DRIVER_OPS, DRM_FBDEV_SHMEM_DRIVER_OPS, -- cgit v1.2.3-59-g8ed1b From 135d8fc7af44c52083e18ccb24d56383d301f741 Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:17 +0100 Subject: drm: writeback: Create an helper for drm_writeback_connector initialization As the old drm and the new drmm variants of drm_writeback_connector requires almost the same initialization, create an internal helper to do most of the initialization work. Currently there is no cleanup function for writeback connectors. To allows implementation of drmm variant of writeback connector, create a cleanup function that can be used to properly remove all the writeback-specific properties and allocations. This also introduce an helper to cleanup only the drm_writeback_connector properties, so it can be used during initialization to cleanup in case of failure. Reviewed-by: Maxime Ripard Acked-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-5-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/drm_writeback.c | 87 +++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index 33a3c98a962d..057af96dafeb 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -202,7 +203,6 @@ EXPORT_SYMBOL(drm_writeback_connector_init); * @dev: DRM device * @wb_connector: Writeback connector to initialize * @enc: handle to the already initialized drm encoder - * @con_funcs: Connector funcs vtable * @formats: Array of supported pixel formats for the writeback engine * @n_formats: Length of the formats array * @@ -218,41 +218,31 @@ EXPORT_SYMBOL(drm_writeback_connector_init); * assigning the encoder helper functions, possible_crtcs and any other encoder * specific operation. * - * Drivers should always use this function instead of drm_connector_init() to - * set up writeback connectors if they want to manage themselves the lifetime of the - * associated encoder. - * * Returns: 0 on success, or a negative error code */ -int drm_writeback_connector_init_with_encoder(struct drm_device *dev, - struct drm_writeback_connector *wb_connector, struct drm_encoder *enc, - const struct drm_connector_funcs *con_funcs, const u32 *formats, - int n_formats) +static int __drm_writeback_connector_init(struct drm_device *dev, + struct drm_writeback_connector *wb_connector, + struct drm_encoder *enc, const u32 *formats, + int n_formats) { - struct drm_property_blob *blob; struct drm_connector *connector = &wb_connector->base; struct drm_mode_config *config = &dev->mode_config; + struct drm_property_blob *blob; int ret = create_writeback_properties(dev); if (ret != 0) return ret; - blob = drm_property_create_blob(dev, n_formats * sizeof(*formats), - formats); - if (IS_ERR(blob)) - return PTR_ERR(blob); - - connector->interlace_allowed = 0; - ret = drm_connector_init(dev, connector, con_funcs, - DRM_MODE_CONNECTOR_WRITEBACK); - if (ret) - goto connector_fail; - ret = drm_connector_attach_encoder(connector, enc); if (ret) - goto attach_fail; + return ret; + + blob = drm_property_create_blob(dev, n_formats * sizeof(*formats), + formats); + if (IS_ERR(blob)) + return PTR_ERR(blob); INIT_LIST_HEAD(&wb_connector->job_queue); spin_lock_init(&wb_connector->job_lock); @@ -275,11 +265,56 @@ int drm_writeback_connector_init_with_encoder(struct drm_device *dev, wb_connector->pixel_formats_blob_ptr = blob; return 0; +} + +/** + * drm_writeback_connector_init_with_encoder - Initialize a writeback connector with + * a custom encoder + * + * @dev: DRM device + * @wb_connector: Writeback connector to initialize + * @enc: handle to the already initialized drm encoder + * @con_funcs: Connector funcs vtable + * @formats: Array of supported pixel formats for the writeback engine + * @n_formats: Length of the formats array + * + * This function creates the writeback-connector-specific properties if they + * have not been already created, initializes the connector as + * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property + * values. + * + * This function assumes that the drm_writeback_connector's encoder has already been + * created and initialized before invoking this function. + * + * In addition, this function also assumes that callers of this API will manage + * assigning the encoder helper functions, possible_crtcs and any other encoder + * specific operation. + * + * Drivers should always use this function instead of drm_connector_init() to + * set up writeback connectors if they want to manage themselves the lifetime of the + * associated encoder. + * + * Returns: 0 on success, or a negative error code + */ +int drm_writeback_connector_init_with_encoder(struct drm_device *dev, + struct drm_writeback_connector *wb_connector, + struct drm_encoder *enc, + const struct drm_connector_funcs *con_funcs, + const u32 *formats, int n_formats) +{ + struct drm_connector *connector = &wb_connector->base; + int ret; + + ret = drm_connector_init(dev, connector, con_funcs, + DRM_MODE_CONNECTOR_WRITEBACK); + if (ret) + return ret; + + ret = __drm_writeback_connector_init(dev, wb_connector, enc, formats, + n_formats); + if (ret) + drm_connector_cleanup(connector); -attach_fail: - drm_connector_cleanup(connector); -connector_fail: - drm_property_blob_put(blob); return ret; } EXPORT_SYMBOL(drm_writeback_connector_init_with_encoder); -- cgit v1.2.3-59-g8ed1b From 2f3f4a73631b160e44ab13d497f7be62264d47ac Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:18 +0100 Subject: drm: writeback: Add missing cleanup in case of initialization failure The current implementation of drm_writeback_connector initialization does not properly clean up all resources in case of failure (allocated properties and possible_encoders). Add this cleaning in case of failure. Acked-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-6-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/drm_writeback.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index 057af96dafeb..4cdc6cdcf76b 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -196,6 +196,22 @@ int drm_writeback_connector_init(struct drm_device *dev, } EXPORT_SYMBOL(drm_writeback_connector_init); +static void delete_writeback_properties(struct drm_device *dev) +{ + if (dev->mode_config.writeback_pixel_formats_property) { + drm_property_destroy(dev, dev->mode_config.writeback_pixel_formats_property); + dev->mode_config.writeback_pixel_formats_property = NULL; + } + if (dev->mode_config.writeback_out_fence_ptr_property) { + drm_property_destroy(dev, dev->mode_config.writeback_out_fence_ptr_property); + dev->mode_config.writeback_out_fence_ptr_property = NULL; + } + if (dev->mode_config.writeback_fb_id_property) { + drm_property_destroy(dev, dev->mode_config.writeback_fb_id_property); + dev->mode_config.writeback_fb_id_property = NULL; + } +} + /** * drm_writeback_connector_init_with_encoder - Initialize a writeback connector with * a custom encoder @@ -231,18 +247,20 @@ static int __drm_writeback_connector_init(struct drm_device *dev, int ret = create_writeback_properties(dev); if (ret != 0) - return ret; + goto failed_properties; connector->interlace_allowed = 0; ret = drm_connector_attach_encoder(connector, enc); if (ret) - return ret; + goto failed_properties; blob = drm_property_create_blob(dev, n_formats * sizeof(*formats), formats); - if (IS_ERR(blob)) - return PTR_ERR(blob); + if (IS_ERR(blob)) { + ret = PTR_ERR(blob); + goto failed_properties; + } INIT_LIST_HEAD(&wb_connector->job_queue); spin_lock_init(&wb_connector->job_lock); @@ -265,6 +283,9 @@ static int __drm_writeback_connector_init(struct drm_device *dev, wb_connector->pixel_formats_blob_ptr = blob; return 0; +failed_properties: + delete_writeback_properties(dev); + return ret; } /** -- cgit v1.2.3-59-g8ed1b From 1914ba2b91ea8eff674e2369f610bb6bb9056745 Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:19 +0100 Subject: drm: writeback: Create drmm variants for drm_writeback_connector initialization To allows driver to only use drmm objects, add helper to create drm_writeback_connectors with automated lifetime management. Acked-by: Thomas Zimmermann Acked-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-7-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/drm_writeback.c | 74 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_writeback.h | 6 ++++ 2 files changed, 80 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index 4cdc6cdcf76b..3628fbef7752 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -340,6 +340,80 @@ int drm_writeback_connector_init_with_encoder(struct drm_device *dev, } EXPORT_SYMBOL(drm_writeback_connector_init_with_encoder); +/** + * drm_writeback_connector_cleanup - Cleanup the writeback connector + * @dev: DRM device + * @wb_connector: Pointer to the writeback connector to clean up + * + * This will decrement the reference counter of blobs and destroy properties. It + * will also clean the remaining jobs in this writeback connector. Caution: This helper will not + * clean up the attached encoder and the drm_connector. + */ +static void drm_writeback_connector_cleanup(struct drm_device *dev, + struct drm_writeback_connector *wb_connector) +{ + unsigned long flags; + struct drm_writeback_job *pos, *n; + + delete_writeback_properties(dev); + drm_property_blob_put(wb_connector->pixel_formats_blob_ptr); + + spin_lock_irqsave(&wb_connector->job_lock, flags); + list_for_each_entry_safe(pos, n, &wb_connector->job_queue, list_entry) { + drm_writeback_cleanup_job(pos); + list_del(&pos->list_entry); + } + spin_unlock_irqrestore(&wb_connector->job_lock, flags); +} + +/** + * drmm_writeback_connector_init - Initialize a writeback connector with + * a custom encoder + * + * @dev: DRM device + * @wb_connector: Writeback connector to initialize + * @con_funcs: Connector funcs vtable + * @enc: Encoder to connect this writeback connector + * @formats: Array of supported pixel formats for the writeback engine + * @n_formats: Length of the formats array + * + * This function initialize a writeback connector and register its cleanup. + * + * This function creates the writeback-connector-specific properties if they + * have not been already created, initializes the connector as + * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property + * values. + * + * Returns: 0 on success, or a negative error code + */ +int drmm_writeback_connector_init(struct drm_device *dev, + struct drm_writeback_connector *wb_connector, + const struct drm_connector_funcs *con_funcs, + struct drm_encoder *enc, + const u32 *formats, int n_formats) +{ + struct drm_connector *connector = &wb_connector->base; + int ret; + + ret = drmm_connector_init(dev, connector, con_funcs, + DRM_MODE_CONNECTOR_WRITEBACK, NULL); + if (ret) + return ret; + + ret = __drm_writeback_connector_init(dev, wb_connector, enc, formats, + n_formats); + if (ret) + return ret; + + ret = drmm_add_action_or_reset(dev, (void *)drm_writeback_connector_cleanup, + wb_connector); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drmm_writeback_connector_init); + int drm_writeback_set_fb(struct drm_connector_state *conn_state, struct drm_framebuffer *fb) { diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h index 17e576c80169..c380a7b8f55a 100644 --- a/include/drm/drm_writeback.h +++ b/include/drm/drm_writeback.h @@ -161,6 +161,12 @@ int drm_writeback_connector_init_with_encoder(struct drm_device *dev, const struct drm_connector_funcs *con_funcs, const u32 *formats, int n_formats); +int drmm_writeback_connector_init(struct drm_device *dev, + struct drm_writeback_connector *wb_connector, + const struct drm_connector_funcs *con_funcs, + struct drm_encoder *enc, + const u32 *formats, int n_formats); + int drm_writeback_set_fb(struct drm_connector_state *conn_state, struct drm_framebuffer *fb); -- cgit v1.2.3-59-g8ed1b From 23fdf4308988b8aee2bb7cf8b77153f822d1fb3a Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Thu, 16 Jan 2025 18:47:20 +0100 Subject: drm/vkms: Switch to managed for writeback connector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current VKMS driver uses non-managed function to create writeback connectors. It is not an issue yet, but in order to support multiple devices easily, convert this code to use drm and device managed helpers. Acked-by: Thomas Zimmermann Acked-by: Maxime Ripard Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v9-8-3e4ae1bd05a0@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.h | 3 ++- drivers/gpu/drm/vkms/vkms_output.c | 2 +- drivers/gpu/drm/vkms/vkms_writeback.c | 21 +++++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 00541eff3d1b..46ac36aebb27 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -179,6 +179,7 @@ struct vkms_output { struct drm_encoder encoder; struct drm_connector connector; struct drm_writeback_connector wb_connector; + struct drm_encoder wb_encoder; struct hrtimer vblank_hrtimer; ktime_t period_ns; struct workqueue_struct *composer_workq; @@ -275,6 +276,6 @@ void vkms_set_composer(struct vkms_output *out, bool enabled); void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y); /* Writeback */ -int vkms_enable_writeback_connector(struct vkms_device *vkmsdev); +int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct drm_crtc *crtc); #endif /* _VKMS_DRV_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index ab9affa75b66..de817e279486 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -95,7 +95,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) } if (vkmsdev->config->writeback) { - writeback = vkms_enable_writeback_connector(vkmsdev); + writeback = vkms_enable_writeback_connector(vkmsdev, crtc); if (writeback) DRM_ERROR("Failed to init writeback connector\n"); } diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 79918b44fedd..981975c2b0a0 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -24,7 +24,6 @@ static const u32 vkms_wb_formats[] = { static const struct drm_connector_funcs vkms_wb_connector_funcs = { .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, @@ -163,16 +162,22 @@ static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = { .atomic_check = vkms_wb_atomic_check, }; -int vkms_enable_writeback_connector(struct vkms_device *vkmsdev) +int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct drm_crtc *crtc) { struct drm_writeback_connector *wb = &vkmsdev->output.wb_connector; + int ret; + + ret = drmm_encoder_init(&vkmsdev->drm, &vkmsdev->output.wb_encoder, + NULL, DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) + return ret; + vkmsdev->output.wb_encoder.possible_crtcs |= drm_crtc_mask(crtc); drm_connector_helper_add(&wb->base, &vkms_wb_conn_helper_funcs); - return drm_writeback_connector_init(&vkmsdev->drm, wb, - &vkms_wb_connector_funcs, - NULL, - vkms_wb_formats, - ARRAY_SIZE(vkms_wb_formats), - 1); + return drmm_writeback_connector_init(&vkmsdev->drm, wb, + &vkms_wb_connector_funcs, + &vkmsdev->output.wb_encoder, + vkms_wb_formats, + ARRAY_SIZE(vkms_wb_formats)); } -- cgit v1.2.3-59-g8ed1b From a20dea718fca0a474ad5773bdc6504d6f5727322 Mon Sep 17 00:00:00 2001 From: Jouni Högander Date: Thu, 9 Jan 2025 12:35:29 +0200 Subject: drm/i915/psr: Add new function for writing sink panel replay enable bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to DP/eDP specification only DP_PANEL_REPLAY_ENABLE has to be set prior link training. For this purpose add a new function which sets this bit on sink side if Panel Replay is supported by the sink and the source. Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20250109103532.2093356-2-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 7 +++++++ drivers/gpu/drm/i915/display/intel_psr.h | 1 + 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 0b021acb330f..266b811bd839 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -827,6 +827,13 @@ void intel_psr_enable_sink(struct intel_dp *intel_dp, drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); } +void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp) +{ + if (CAN_PANEL_REPLAY(intel_dp)) + drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG, + DP_PANEL_REPLAY_ENABLE); +} + static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index 956be263c09e..3b2643b83e06 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -30,6 +30,7 @@ bool intel_psr_needs_aux_io_power(struct intel_encoder *encoder, void intel_psr_init_dpcd(struct intel_dp *intel_dp); void intel_psr_enable_sink(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp); void intel_psr_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_psr_post_plane_update(struct intel_atomic_state *state, -- cgit v1.2.3-59-g8ed1b From 68f3a505b367656a2db05406a62dc43fb0c50034 Mon Sep 17 00:00:00 2001 From: Jouni Högander Date: Thu, 9 Jan 2025 12:35:30 +0200 Subject: drm/i915/psr: Enable Panel Replay on sink always when it's supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are configuring Panel Replay on sink when it get's enabled. This means we need to do full modeset when enabling Panel Replay. This is required as DP specification is saying sink Panel Replay needs to be configured before link training. Avoid full modeset by enabling Panel Replay on sink always when it's supported by the sink and the source. Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20250109103532.2093356-3-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index acb986bc1f33..3693b36b9336 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2927,8 +2927,7 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state, crtc_state); /* Panel replay has to be enabled in sink dpcd before link training. */ - if (crtc_state->has_panel_replay) - intel_psr_enable_sink(enc_to_intel_dp(encoder), crtc_state); + intel_psr_panel_replay_enable_sink(enc_to_intel_dp(encoder)); if (DISPLAY_VER(display) >= 14) mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state); -- cgit v1.2.3-59-g8ed1b From 4917c46411164dd1aa22611577ab751cb66e04b9 Mon Sep 17 00:00:00 2001 From: Jouni Högander Date: Thu, 9 Jan 2025 12:35:31 +0200 Subject: drm/i915/psr: Make intel_psr_enable_sink as local static function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel_psr_enable_sink is not used outside intel_psr.c. Convert it as local static function. Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20250109103532.2093356-4-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 4 ++-- drivers/gpu/drm/i915/display/intel_psr.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 266b811bd839..797199ba1cbf 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -814,8 +814,8 @@ static void intel_psr_enable_sink_alpm(struct intel_dp *intel_dp, drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val); } -void intel_psr_enable_sink(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +static void intel_psr_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { intel_psr_enable_sink_alpm(intel_dp, crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index 3b2643b83e06..5f1671d02d76 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -28,8 +28,6 @@ bool intel_encoder_can_psr(struct intel_encoder *encoder); bool intel_psr_needs_aux_io_power(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_psr_init_dpcd(struct intel_dp *intel_dp); -void intel_psr_enable_sink(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp); void intel_psr_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc); -- cgit v1.2.3-59-g8ed1b From edbfa38ffa822ab2fe6848a61b339f27a34c4b22 Mon Sep 17 00:00:00 2001 From: Jouni Högander Date: Thu, 9 Jan 2025 12:35:32 +0200 Subject: drm/i915/psr: Allow changing Panel Replay mode without full modeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are forcing full modeset if Panel Replay mode is changed. This is not necessary as long as we are not changing sink PANEL REPLAY ENABLE bit in PANEL REPLAY ENABLE AND CONFIGURATION 1 register. This can be achieved by entering Panel Replay inactive mode (Live Frame mode) when Panel Replay is disabled and keep PANEL REPLAY ENABLE bit in PANEL REPLAY ENABLE AND CONFIGURATION 1 enabled always if panel is just supporting Panel Replay. Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20250109103532.2093356-5-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 14 -------------- drivers/gpu/drm/i915/display/intel_psr.c | 25 +++++++++++++++++-------- 2 files changed, 17 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 15f298d0424a..e63619da2e62 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5673,20 +5673,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_CSC(output_csc); } - /* - * Panel replay has to be enabled before link training. PSR doesn't have - * this requirement -> check these only if using panel replay - */ - if (current_config->active_planes && - (current_config->has_panel_replay || - pipe_config->has_panel_replay)) { - PIPE_CONF_CHECK_BOOL(has_psr); - PIPE_CONF_CHECK_BOOL(has_sel_update); - PIPE_CONF_CHECK_BOOL(enable_psr2_sel_fetch); - PIPE_CONF_CHECK_BOOL(enable_psr2_su_region_et); - PIPE_CONF_CHECK_BOOL(has_panel_replay); - } - PIPE_CONF_CHECK_BOOL(double_wide); if (dev_priv->display.dpll.mgr) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 797199ba1cbf..aa6ff057b54c 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1998,18 +1998,25 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, if (!psr_interrupt_error_check(intel_dp)) return; - if (intel_dp->psr.panel_replay_enabled) { + if (intel_dp->psr.panel_replay_enabled) drm_dbg_kms(display->drm, "Enabling Panel Replay\n"); - } else { + else drm_dbg_kms(display->drm, "Enabling PSR%s\n", intel_dp->psr.sel_update_enabled ? "2" : "1"); - /* - * Panel replay has to be enabled before link training: doing it - * only for PSR here. - */ - intel_psr_enable_sink(intel_dp, crtc_state); - } + /* + * Enabling here only for PSR. Panel Replay enable bit is already + * written at this point. See + * intel_psr_panel_replay_enable_sink. Modifiers/options: + * - Selective Update + * - Region Early Transport + * - Selective Update Region Scanline Capture + * - VSC_SDP_CRC + * - HPD on different Errors + * - CRC verification + * are written for PSR and Panel Replay here. + */ + intel_psr_enable_sink(intel_dp, crtc_state); if (intel_dp_is_edp(intel_dp)) intel_snps_phy_update_psr_power_state(&dig_port->base, true); @@ -2815,6 +2822,8 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, needs_to_disable |= new_crtc_state->has_sel_update != psr->sel_update_enabled; needs_to_disable |= new_crtc_state->enable_psr2_su_region_et != psr->su_region_et_enabled; + needs_to_disable |= new_crtc_state->has_panel_replay != + psr->panel_replay_enabled; needs_to_disable |= DISPLAY_VER(i915) < 11 && new_crtc_state->wm_level_disabled; -- cgit v1.2.3-59-g8ed1b From b0a76faea6b1492e480a69ef1a6cd19e30e7d60d Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Fri, 17 Jan 2025 10:04:27 +0100 Subject: drm/vkms: Switch to dynamic allocation for connector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A specific allocation for the connector is not strictly necessary at this point, but in order to implement dynamic configuration of VKMS (configFS), it will be easier to have one allocation per connector. Reviewed-by: Maxime Ripard Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20250117-b4-vkms-allocated-v4-1-8ec8fd21aaf6@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.h | 1 - drivers/gpu/drm/vkms/vkms_output.c | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 46ac36aebb27..afa625457b61 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -177,7 +177,6 @@ struct vkms_crtc_state { struct vkms_output { struct drm_crtc crtc; struct drm_encoder encoder; - struct drm_connector connector; struct drm_writeback_connector wb_connector; struct drm_encoder wb_encoder; struct hrtimer vblank_hrtimer; diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index de817e279486..a41d7a29a377 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -32,7 +32,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) { struct vkms_output *output = &vkmsdev->output; struct drm_device *dev = &vkmsdev->drm; - struct drm_connector *connector = &output->connector; + struct drm_connector *connector; struct drm_encoder *encoder = &output->encoder; struct drm_crtc *crtc = &output->crtc; struct vkms_plane *primary, *overlay, *cursor = NULL; @@ -71,6 +71,12 @@ int vkms_output_init(struct vkms_device *vkmsdev) } } + connector = drmm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); + if (!connector) { + DRM_ERROR("Failed to allocate connector\n"); + return -ENOMEM; + } + ret = drmm_connector_init(dev, connector, &vkms_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL, NULL); if (ret) { -- cgit v1.2.3-59-g8ed1b From 45a4778415736fe4649a9fac2323091cdd710d86 Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Fri, 17 Jan 2025 10:04:28 +0100 Subject: drm/vkms: Switch to dynamic allocation for encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A specific allocation for the encoder is not strictly necessary at this point, but in order to implement dynamic configuration of VKMS (configFS), it will be easier to have one allocation per encoder. Reviewed-by: Maxime Ripard Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20250117-b4-vkms-allocated-v4-2-8ec8fd21aaf6@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.h | 1 - drivers/gpu/drm/vkms/vkms_output.c | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index afa625457b61..333983bcf8d4 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -176,7 +176,6 @@ struct vkms_crtc_state { */ struct vkms_output { struct drm_crtc crtc; - struct drm_encoder encoder; struct drm_writeback_connector wb_connector; struct drm_encoder wb_encoder; struct hrtimer vblank_hrtimer; diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index a41d7a29a377..21ca975e424d 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -33,7 +33,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) struct vkms_output *output = &vkmsdev->output; struct drm_device *dev = &vkmsdev->drm; struct drm_connector *connector; - struct drm_encoder *encoder = &output->encoder; + struct drm_encoder *encoder; struct drm_crtc *crtc = &output->crtc; struct vkms_plane *primary, *overlay, *cursor = NULL; int ret; @@ -86,6 +86,11 @@ int vkms_output_init(struct vkms_device *vkmsdev) drm_connector_helper_add(connector, &vkms_conn_helper_funcs); + encoder = drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); + if (!encoder) { + DRM_ERROR("Failed to allocate encoder\n"); + return -ENOMEM; + } ret = drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_VIRTUAL, NULL); if (ret) { -- cgit v1.2.3-59-g8ed1b From 49a167c393b0ceb592b9d2e65cc4f46bcc707108 Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Fri, 17 Jan 2025 10:04:29 +0100 Subject: drm/vkms: Switch to dynamic allocation for CRTC A specific allocation for the CRTC is not strictly necessary at this point, but in order to implement dynamic configuration of VKMS (configFS), it will be easier to have one allocation per CRTC. Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250117-b4-vkms-allocated-v4-3-8ec8fd21aaf6@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_crtc.c | 32 +++++++++++++++++--------------- drivers/gpu/drm/vkms/vkms_drv.h | 8 ++++---- drivers/gpu/drm/vkms/vkms_output.c | 22 ++++++++++++---------- drivers/gpu/drm/vkms/vkms_writeback.c | 23 ++++++++++++----------- 4 files changed, 45 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 434c35d5e947..cf229aec71c3 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -84,9 +84,7 @@ static bool vkms_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, bool in_vblank_irq) { - struct drm_device *dev = crtc->dev; - struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); - struct vkms_output *output = &vkmsdev->output; + struct vkms_output *output = drm_crtc_to_vkms_output(crtc); struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); if (!READ_ONCE(vblank->enabled)) { @@ -271,25 +269,29 @@ static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = { .atomic_disable = vkms_crtc_atomic_disable, }; -int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, - struct drm_plane *primary, struct drm_plane *cursor) +struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *primary, + struct drm_plane *cursor) { - struct vkms_output *vkms_out = drm_crtc_to_vkms_output(crtc); + struct vkms_output *vkms_out; + struct drm_crtc *crtc; int ret; - ret = drmm_crtc_init_with_planes(dev, crtc, primary, cursor, - &vkms_crtc_funcs, NULL); - if (ret) { - DRM_ERROR("Failed to init CRTC\n"); - return ret; + vkms_out = drmm_crtc_alloc_with_planes(dev, struct vkms_output, crtc, + primary, cursor, + &vkms_crtc_funcs, NULL); + if (IS_ERR(vkms_out)) { + DRM_DEV_ERROR(dev->dev, "Failed to init CRTC\n"); + return vkms_out; } + crtc = &vkms_out->crtc; + drm_crtc_helper_add(crtc, &vkms_crtc_helper_funcs); ret = drm_mode_crtc_set_gamma_size(crtc, VKMS_LUT_SIZE); if (ret) { DRM_ERROR("Failed to set gamma size\n"); - return ret; + return ERR_PTR(ret); } drm_crtc_enable_color_mgmt(crtc, 0, false, VKMS_LUT_SIZE); @@ -299,9 +301,9 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, vkms_out->composer_workq = drmm_alloc_ordered_workqueue(dev, "vkms_composer", 0); if (IS_ERR(vkms_out->composer_workq)) - return PTR_ERR(vkms_out->composer_workq); + return ERR_CAST(vkms_out->composer_workq); if (!vkms_out->composer_workq) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - return ret; + return vkms_out; } diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 333983bcf8d4..abbb652be2b5 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -215,7 +215,6 @@ struct vkms_config { struct vkms_device { struct drm_device drm; struct platform_device *platform; - struct vkms_output output; const struct vkms_config *config; }; @@ -242,8 +241,9 @@ struct vkms_device { * @primary: primary plane to attach to the CRTC * @cursor: plane to attach to the CRTC */ -int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, - struct drm_plane *primary, struct drm_plane *cursor); +struct vkms_output *vkms_crtc_init(struct drm_device *dev, + struct drm_plane *primary, + struct drm_plane *cursor); /** * vkms_output_init() - Initialize all sub-components needed for a VKMS device. @@ -274,6 +274,6 @@ void vkms_set_composer(struct vkms_output *out, bool enabled); void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y); /* Writeback */ -int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct drm_crtc *crtc); +int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_output *vkms_out); #endif /* _VKMS_DRV_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 21ca975e424d..22f0d678af3a 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -30,11 +30,10 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = { int vkms_output_init(struct vkms_device *vkmsdev) { - struct vkms_output *output = &vkmsdev->output; struct drm_device *dev = &vkmsdev->drm; struct drm_connector *connector; struct drm_encoder *encoder; - struct drm_crtc *crtc = &output->crtc; + struct vkms_output *output; struct vkms_plane *primary, *overlay, *cursor = NULL; int ret; int writeback; @@ -56,9 +55,12 @@ int vkms_output_init(struct vkms_device *vkmsdev) return PTR_ERR(cursor); } - ret = vkms_crtc_init(dev, crtc, &primary->base, &cursor->base); - if (ret) - return ret; + output = vkms_crtc_init(dev, &primary->base, + cursor ? &cursor->base : NULL); + if (IS_ERR(output)) { + DRM_ERROR("Failed to allocate CRTC\n"); + return PTR_ERR(output); + } if (vkmsdev->config->overlay) { for (n = 0; n < NUM_OVERLAY_PLANES; n++) { @@ -67,7 +69,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n"); return PTR_ERR(overlay); } - overlay->base.possible_crtcs = drm_crtc_mask(crtc); + overlay->base.possible_crtcs = drm_crtc_mask(&output->crtc); } } @@ -97,23 +99,23 @@ int vkms_output_init(struct vkms_device *vkmsdev) DRM_ERROR("Failed to init encoder\n"); return ret; } - encoder->possible_crtcs = drm_crtc_mask(crtc); + encoder->possible_crtcs = drm_crtc_mask(&output->crtc); + /* Attach the encoder and the connector */ ret = drm_connector_attach_encoder(connector, encoder); if (ret) { DRM_ERROR("Failed to attach connector to encoder\n"); return ret; } + /* Initialize the writeback component */ if (vkmsdev->config->writeback) { - writeback = vkms_enable_writeback_connector(vkmsdev, crtc); + writeback = vkms_enable_writeback_connector(vkmsdev, output); if (writeback) DRM_ERROR("Failed to init writeback connector\n"); } drm_mode_config_reset(dev); - return 0; - return ret; } diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 981975c2b0a0..e9b5c74d7c58 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -105,7 +105,9 @@ static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector, struct drm_writeback_job *job) { struct vkms_writeback_job *vkmsjob = job->priv; - struct vkms_device *vkmsdev; + struct vkms_output *vkms_output = container_of(connector, + struct vkms_output, + wb_connector); if (!job->fb) return; @@ -114,8 +116,7 @@ static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector, drm_framebuffer_put(vkmsjob->wb_frame_info.fb); - vkmsdev = drm_device_to_vkms_device(job->fb->dev); - vkms_set_composer(&vkmsdev->output, false); + vkms_set_composer(vkms_output, false); kfree(vkmsjob); } @@ -124,8 +125,7 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, { struct drm_connector_state *connector_state = drm_atomic_get_new_connector_state(state, conn); - struct vkms_device *vkmsdev = drm_device_to_vkms_device(conn->dev); - struct vkms_output *output = &vkmsdev->output; + struct vkms_output *output = drm_crtc_to_vkms_output(connector_state->crtc); 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; @@ -139,7 +139,7 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, if (!conn_state) return; - vkms_set_composer(&vkmsdev->output, true); + vkms_set_composer(output, true); active_wb = conn_state->writeback_job->priv; wb_frame_info = &active_wb->wb_frame_info; @@ -162,22 +162,23 @@ static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = { .atomic_check = vkms_wb_atomic_check, }; -int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct drm_crtc *crtc) +int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, + struct vkms_output *vkms_output) { - struct drm_writeback_connector *wb = &vkmsdev->output.wb_connector; + struct drm_writeback_connector *wb = &vkms_output->wb_connector; int ret; - ret = drmm_encoder_init(&vkmsdev->drm, &vkmsdev->output.wb_encoder, + ret = drmm_encoder_init(&vkmsdev->drm, &vkms_output->wb_encoder, NULL, DRM_MODE_ENCODER_VIRTUAL, NULL); if (ret) return ret; - vkmsdev->output.wb_encoder.possible_crtcs |= drm_crtc_mask(crtc); + vkms_output->wb_encoder.possible_crtcs |= drm_crtc_mask(&vkms_output->crtc); drm_connector_helper_add(&wb->base, &vkms_wb_conn_helper_funcs); return drmm_writeback_connector_init(&vkmsdev->drm, wb, &vkms_wb_connector_funcs, - &vkmsdev->output.wb_encoder, + &vkms_output->wb_encoder, vkms_wb_formats, ARRAY_SIZE(vkms_wb_formats)); } -- cgit v1.2.3-59-g8ed1b From f3b59457808f61d88178b0afa67cbd017d7ce79e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 10 Dec 2024 09:31:11 +0100 Subject: drm/xe: Do not attempt to bootstrap VF in execlists mode It was mentioned in a review that there is a possibility of choosing to load the module with VF in execlists mode. Of course this doesn't work, just bomb out as hard as possible. Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-12-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index cca5d5732802..6671030439fd 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -213,6 +213,9 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt) { int err; + if (!xe_device_uc_enabled(gt_to_xe(gt))) + return -ENODEV; + err = vf_reset_guc_state(gt); if (unlikely(err)) return err; -- cgit v1.2.3-59-g8ed1b From 380b0cdaa76bc8f5c16db16eaf48751e792ff041 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 10 Dec 2024 09:31:03 +0100 Subject: drm/xe: Move suballocator init to after display init No allocations should be done before we have had a chance to preserve the display fb. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-4-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_device.c | 6 ++++++ drivers/gpu/drm/xe/xe_tile.c | 12 ++++++++---- drivers/gpu/drm/xe/xe_tile.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 6ecbf7dd396c..af9b2bb62dee 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -840,6 +840,12 @@ int xe_device_probe(struct xe_device *xe) if (err) goto err; + for_each_tile(tile, xe, id) { + err = xe_tile_init(tile); + if (err) + goto err; + } + for_each_gt(gt, xe, id) { last_gt = id; diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c index 07cf7cfe4abd..2825553b568f 100644 --- a/drivers/gpu/drm/xe/xe_tile.c +++ b/drivers/gpu/drm/xe/xe_tile.c @@ -170,10 +170,6 @@ int xe_tile_init_noalloc(struct xe_tile *tile) if (err) return err; - tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); - if (IS_ERR(tile->mem.kernel_bb_pool)) - return PTR_ERR(tile->mem.kernel_bb_pool); - xe_wa_apply_tile_workarounds(tile); err = xe_tile_sysfs_init(tile); @@ -181,6 +177,14 @@ int xe_tile_init_noalloc(struct xe_tile *tile) return 0; } +int xe_tile_init(struct xe_tile *tile) +{ + tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); + if (IS_ERR(tile->mem.kernel_bb_pool)) + return PTR_ERR(tile->mem.kernel_bb_pool); + + return 0; +} void xe_tile_migrate_wait(struct xe_tile *tile) { xe_migrate_wait(tile->migrate); diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h index 1c9e42ade6b0..eb939316d55b 100644 --- a/drivers/gpu/drm/xe/xe_tile.h +++ b/drivers/gpu/drm/xe/xe_tile.h @@ -12,6 +12,7 @@ struct xe_tile; int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id); int xe_tile_init_noalloc(struct xe_tile *tile); +int xe_tile_init(struct xe_tile *tile); void xe_tile_migrate_wait(struct xe_tile *tile); -- cgit v1.2.3-59-g8ed1b From 2218704997979fbf11765281ef752f07c5cf25bb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 10 Dec 2024 09:31:02 +0100 Subject: drm/xe: Remove double pageflip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is already handled below in the code by fixup_initial_plane_config. Fixes: a8153627520a ("drm/i915: Try to relocate the BIOS fb to the start of ggtt") Cc: Ville Syrjälä Reviewed-by: Vinod Govindapillai Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-3-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/display/xe_plane_initial.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 2eb9633f163a..2a2f250fa495 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -194,8 +194,6 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, to_intel_plane(crtc->base.primary); struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); struct drm_framebuffer *fb; struct i915_vma *vma; @@ -241,14 +239,6 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits); plane_config->vma = vma; - - /* - * Flip to the newly created mapping ASAP, so we can re-use the - * first part of GGTT for WOPCM, prevent flickering, and prevent - * the lookup of sysmem scratch pages. - */ - plane->check_plane(crtc_state, plane_state); - plane->async_flip(NULL, plane, crtc_state, plane_state, true); return; nofb: -- cgit v1.2.3-59-g8ed1b From 8a2392fec5b4b96d738feb6ecef02b9958bb64b1 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 17 Jan 2025 17:38:43 +0200 Subject: drm/xe/dp: Fix non-display builds with DP tunnelling incorrectly enabled Code for the DP tunnelling functionality in the xe driver can be built only if the display code is also built, adjust the kconfig dependency accordingly. Cc: Suraj Kandpal Fixes: 73900dce57e4 ("drm/xe/dp: Enable DP tunneling") Reported-by: Lucas De Marchi Reviewed-by: Suraj Kandpal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250117153843.1312303-1-imre.deak@intel.com --- drivers/gpu/drm/xe/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index 50cf80df5190..99219c16e8aa 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -61,7 +61,7 @@ config DRM_XE_DISPLAY config DRM_XE_DP_TUNNEL bool "Enable DP tunnel support" - depends on DRM_XE + depends on DRM_XE_DISPLAY depends on USB4 select DRM_DISPLAY_DP_TUNNEL default y -- cgit v1.2.3-59-g8ed1b From c5303240e01919ea9cd3a2e198c3a25686a99552 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:30 +0200 Subject: drm/i915: Keep TRANS_VBLANK.vblank_start==0 on ADL+ even when doing LRR updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_set_transcoder_timings() will set TRANS_VBLANK.vblank_start to 0 for clarity on ADL+ (non-DSI) because the hardware no longer uses that value. Do the same in intel_set_transcoder_timings_lrr() to make sure the registers stay consistent even when doing LRR timing updates. Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e63619da2e62..34b8a54f95a3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2923,6 +2923,14 @@ static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state *crtc crtc_vblank_start = adjusted_mode->crtc_vblank_start; crtc_vblank_end = adjusted_mode->crtc_vblank_end; + if (DISPLAY_VER(dev_priv) >= 13) { + /* + * VBLANK_START not used by hw, just clear it + * to make it stand out in register dumps. + */ + crtc_vblank_start = 1; + } + drm_WARN_ON(&dev_priv->drm, adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE); /* -- cgit v1.2.3-59-g8ed1b From 880426962795b763f209a0b7fcd5df815664aaf8 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:31 +0200 Subject: drm/i915: Handle interlaced modes in intel_set_transcoder_timings_lrr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I want to start using intel_set_transcoder_timings_lrr() also for fixing up the vblank delay during boot. To that end make sure it can cope with interlaced modes as well. Note that we have soft-defeatured interlaced modes on tgl+ so technically this is dead code, but if we ever have the need to bring interlaced support back it seems better to handle this. Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 34b8a54f95a3..29879ad0ed56 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2923,6 +2923,12 @@ static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state *crtc crtc_vblank_start = adjusted_mode->crtc_vblank_start; crtc_vblank_end = adjusted_mode->crtc_vblank_end; + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + /* the chip adds 2 halflines automatically */ + crtc_vtotal -= 1; + crtc_vblank_end -= 1; + } + if (DISPLAY_VER(dev_priv) >= 13) { /* * VBLANK_START not used by hw, just clear it @@ -2931,8 +2937,6 @@ static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state *crtc crtc_vblank_start = 1; } - drm_WARN_ON(&dev_priv->drm, adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE); - /* * The hardware actually ignores TRANS_VBLANK.VBLANK_END in DP mode. * But let's write it anyway to keep the state checker happy. -- cgit v1.2.3-59-g8ed1b From d6d4dc22d50312132ea312f1074e4367e219254c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:32 +0200 Subject: drm/i915: Update TRANS_SET_CONTEXT_LATENCY during LRR updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update TRANS_SET_CONTEXT_LATENCY in intel_set_transcoder_timings_lrr() as well. While for actual LRR updates this should not change, I want to reuse this code to also sanitize the vblank delay during boot, and in that case we do need to update this. Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 29879ad0ed56..e6501143ab7c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2930,6 +2930,10 @@ static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state *crtc } if (DISPLAY_VER(dev_priv) >= 13) { + intel_de_write(dev_priv, + TRANS_SET_CONTEXT_LATENCY(dev_priv, cpu_transcoder), + crtc_vblank_start - crtc_vdisplay); + /* * VBLANK_START not used by hw, just clear it * to make it stand out in register dumps. -- cgit v1.2.3-59-g8ed1b From 1f1b673cec361b4ab20b817340f74e75d070f312 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:33 +0200 Subject: drm/i915: Warn if someone tries to use intel_set_transcoder_timings*() on DSI outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_set_transcoder_timings*() aren't currently suitable for DSI. Warn if someone accidentally calls them in such cases. Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e6501143ab7c..d0989a85e59c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2837,6 +2837,8 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta u32 crtc_vdisplay, crtc_vtotal, crtc_vblank_start, crtc_vblank_end; int vsyncshift = 0; + drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder)); + /* We need to be careful not to changed the adjusted mode, for otherwise * the hw state checker will get angry at the mismatch. */ crtc_vdisplay = adjusted_mode->crtc_vdisplay; @@ -2918,6 +2920,8 @@ static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state *crtc const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 crtc_vdisplay, crtc_vtotal, crtc_vblank_start, crtc_vblank_end; + drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder)); + crtc_vdisplay = adjusted_mode->crtc_vdisplay; crtc_vtotal = adjusted_mode->crtc_vtotal; crtc_vblank_start = adjusted_mode->crtc_vblank_start; -- cgit v1.2.3-59-g8ed1b From ff118b4f0c05ee55e049db2beefbbd2f43298fbd Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:34 +0200 Subject: drm/i915: Extract lrr_params_changed() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the "do we actually need a LRR update?" checks into a small helper for clarity. Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d0989a85e59c..b5e38137ef4d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6067,6 +6067,13 @@ static int intel_modeset_checks(struct intel_atomic_state *state) return 0; } +static bool lrr_params_changed(const struct drm_display_mode *old_adjusted_mode, + const struct drm_display_mode *new_adjusted_mode) +{ + return old_adjusted_mode->crtc_vblank_end != new_adjusted_mode->crtc_vblank_end || + old_adjusted_mode->crtc_vtotal != new_adjusted_mode->crtc_vtotal; +} + static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state) { @@ -6087,8 +6094,8 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta &new_crtc_state->dp_m_n)) new_crtc_state->update_m_n = false; - if ((old_crtc_state->hw.adjusted_mode.crtc_vtotal == new_crtc_state->hw.adjusted_mode.crtc_vtotal && - old_crtc_state->hw.adjusted_mode.crtc_vblank_end == new_crtc_state->hw.adjusted_mode.crtc_vblank_end)) + if (!lrr_params_changed(&old_crtc_state->hw.adjusted_mode, + &new_crtc_state->hw.adjusted_mode)) new_crtc_state->update_lrr = false; if (intel_crtc_needs_modeset(new_crtc_state)) -- cgit v1.2.3-59-g8ed1b From 42fdbe94b69ceed77622e58b33701546f49283a4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:35 +0200 Subject: drm/i915: Allow fastboot to fix up the vblank delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GOP might not agree with our idea of what the vblank delay should be. Reuse the LRR codepaths to fix that up via a fastset. The relevant registers aren't actually double buffered so this is a little bit dodgy. While I've not seen any real issues from frobbing these live, let's limit this to just the fastboot case (by only allowing it when old_crtc_state->inherited==true). Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b5e38137ef4d..950505c94224 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5358,6 +5358,19 @@ pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset, intel_cx0pll_dump_hw_state(display, b); } +static bool allow_vblank_delay_fastset(const struct intel_crtc_state *old_crtc_state) +{ + struct intel_display *display = to_intel_display(old_crtc_state); + + /* + * Allow fastboot to fix up vblank delay (handled via LRR + * codepaths), a bit dodgy as the registers aren't + * double buffered but seems to be working more or less... + */ + return HAS_LRR(display) && old_crtc_state->inherited && + !intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI); +} + bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, @@ -5490,7 +5503,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(name.crtc_hsync_start); \ PIPE_CONF_CHECK_I(name.crtc_hsync_end); \ PIPE_CONF_CHECK_I(name.crtc_vdisplay); \ - PIPE_CONF_CHECK_I(name.crtc_vblank_start); \ + if (!fastset || !allow_vblank_delay_fastset(current_config)) \ + PIPE_CONF_CHECK_I(name.crtc_vblank_start); \ PIPE_CONF_CHECK_I(name.crtc_vsync_start); \ PIPE_CONF_CHECK_I(name.crtc_vsync_end); \ if (!fastset || !pipe_config->update_lrr) { \ @@ -6070,7 +6084,8 @@ static int intel_modeset_checks(struct intel_atomic_state *state) static bool lrr_params_changed(const struct drm_display_mode *old_adjusted_mode, const struct drm_display_mode *new_adjusted_mode) { - return old_adjusted_mode->crtc_vblank_end != new_adjusted_mode->crtc_vblank_end || + return old_adjusted_mode->crtc_vblank_start != new_adjusted_mode->crtc_vblank_start || + old_adjusted_mode->crtc_vblank_end != new_adjusted_mode->crtc_vblank_end || old_adjusted_mode->crtc_vtotal != new_adjusted_mode->crtc_vtotal; } @@ -6084,11 +6099,14 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta if (old_crtc_state->vrr.in_range != new_crtc_state->vrr.in_range) new_crtc_state->update_lrr = false; - if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true)) + if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true)) { drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] fastset requirement not met, forcing full modeset\n", crtc->base.base.id, crtc->base.name); - else + } else { + if (allow_vblank_delay_fastset(old_crtc_state)) + new_crtc_state->update_lrr = true; new_crtc_state->uapi.mode_changed = false; + } if (intel_compare_link_m_n(&old_crtc_state->dp_m_n, &new_crtc_state->dp_m_n)) -- cgit v1.2.3-59-g8ed1b From aee21ab36e142c10fa6b56694b9d160fb5a49abb Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:36 +0200 Subject: drm/i915/dsb: Add support for triggering VRR push with DSB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have at least two options for how to do the TRANS_PUSH_SEND + commit completion signalling with the DSB: Option A) 1. trigger TRANS_PUSH_SEND 2. wait for "safe window" 3. signal the interrupt In this cases step 2 should not do anything if we were already between vmin and vmax decision boundaries. Otherwise we'll wait until the next start of the vblank period. Option B) 1. wait for "safe window" 2. trigger TRANS_PUSH_SEND 3. signal the interrupt This option is perhaps a bit less racy, but if we do somehow screw up and the wait is a nop but the push gets deferred until the next frame then we'll end up completing the commit a frame too early. So for now I'm leaning towards option A since losing the race won't have any drastic consequences. To deal with the race we can give the DSB a bit more time to start step 2 before the hardware has started the vblank termination properly. Often times it seems to be fast enough to make it in time even without any extra vblank delay (the push is issued somewhere within a scanline and it latches on the next scanline). v2: Use intel_vrr_possible() to determine if we need some vblank delay (also avoids adding it for DSI which doens't actually program the transcoder registers correctly for it) Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Reviewed-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 950505c94224..68d932d9f5c5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2630,6 +2630,14 @@ static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state) if (intel_crtc_needs_wa_14015401596(crtc_state)) vblank_delay = max(vblank_delay, 1); + /* + * Add a minimal vblank delay to make sure the push + * doesn't race with the "wait for safe window" used + * for frame completion with DSB. + */ + if (intel_vrr_possible(crtc_state)) + vblank_delay = max(vblank_delay, 1); + return vblank_delay; } @@ -7727,6 +7735,8 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, intel_crtc_planes_update_arm(new_crtc_state->dsb_commit, state, crtc); + intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state); + if (!new_crtc_state->dsb_color_vblank) { intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1); intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit); -- cgit v1.2.3-59-g8ed1b From 83db7bf1781dab848adf1280ee45bb4f93b52f27 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jan 2025 22:16:37 +0200 Subject: drm/i915/dsb: Allow DSB to perform commits when VRR is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we know how to issue the push with the DSB we can allow the DSB to drive the commits even when VRR is active. Cc: Paz Zcharya Signed-off-by: Ville Syrjälä Reviewed-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250116201637.22486-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 68d932d9f5c5..10550bc0778e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7694,7 +7694,6 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state, /* FIXME deal with everything */ new_crtc_state->use_dsb = new_crtc_state->update_planes && - !new_crtc_state->vrr.enable && !new_crtc_state->do_async_flip && !new_crtc_state->has_psr && !new_crtc_state->scaler_state.scaler_users && -- cgit v1.2.3-59-g8ed1b From cfa9d40db8c30d894171010fe765d96e9bc6a47e Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Thu, 16 Jan 2025 19:21:55 -0800 Subject: drm/xe/oa: Preserve oa_ctrl unused bits UMD's have interest in setting unused bits of the oa_ctrl register "out of band" for certain experiments. To facilitate this, don't clobber previous oa_ctrl unused bits, i.e. rmw the values rather than simply write them. Fixes: e936f885f1e9 ("drm/xe/oa/uapi: Expose OA stream fd") Signed-off-by: Ashutosh Dixit Reviewed-by: Umesh Nerlige Ramappa Link: https://patchwork.freedesktop.org/patch/msgid/20250117032155.3048063-1-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/regs/xe_oa_regs.h | 6 ++++++ drivers/gpu/drm/xe/xe_oa.c | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/regs/xe_oa_regs.h b/drivers/gpu/drm/xe/regs/xe_oa_regs.h index a49561e9f3c3..a79ad2da070c 100644 --- a/drivers/gpu/drm/xe/regs/xe_oa_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_oa_regs.h @@ -51,6 +51,10 @@ /* Common to all OA units */ #define OA_OACONTROL_REPORT_BC_MASK REG_GENMASK(9, 9) #define OA_OACONTROL_COUNTER_SIZE_MASK REG_GENMASK(8, 8) +#define OAG_OACONTROL_USED_BITS \ + (OAG_OACONTROL_OA_PES_DISAG_EN | OAG_OACONTROL_OA_CCS_SELECT_MASK | \ + OAG_OACONTROL_OA_COUNTER_SEL_MASK | OAG_OACONTROL_OA_COUNTER_ENABLE | \ + OA_OACONTROL_REPORT_BC_MASK | OA_OACONTROL_COUNTER_SIZE_MASK) #define OAG_OA_DEBUG XE_REG(0xdaf8, XE_REG_OPTION_MASKED) #define OAG_OA_DEBUG_DISABLE_MMIO_TRG REG_BIT(14) @@ -78,6 +82,8 @@ #define OAM_CONTEXT_CONTROL_OFFSET (0x1bc) #define OAM_CONTROL_OFFSET (0x194) #define OAM_CONTROL_COUNTER_SEL_MASK REG_GENMASK(3, 1) +#define OAM_OACONTROL_USED_BITS \ + (OAM_CONTROL_COUNTER_SEL_MASK | OAG_OACONTROL_OA_COUNTER_ENABLE) #define OAM_DEBUG_OFFSET (0x198) #define OAM_STATUS_OFFSET (0x19c) #define OAM_MMIO_TRG_OFFSET (0x1d0) diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index eeb96b5f49e2..6a08e6c92835 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -452,6 +452,12 @@ static u32 __oa_ccs_select(struct xe_oa_stream *stream) return val; } +static u32 __oactrl_used_bits(struct xe_oa_stream *stream) +{ + return stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG ? + OAG_OACONTROL_USED_BITS : OAM_OACONTROL_USED_BITS; +} + static void xe_oa_enable(struct xe_oa_stream *stream) { const struct xe_oa_format *format = stream->oa_buffer.format; @@ -472,14 +478,14 @@ static void xe_oa_enable(struct xe_oa_stream *stream) stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG) val |= OAG_OACONTROL_OA_PES_DISAG_EN; - xe_mmio_write32(&stream->gt->mmio, regs->oa_ctrl, val); + xe_mmio_rmw32(&stream->gt->mmio, regs->oa_ctrl, __oactrl_used_bits(stream), val); } static void xe_oa_disable(struct xe_oa_stream *stream) { struct xe_mmio *mmio = &stream->gt->mmio; - xe_mmio_write32(mmio, __oa_regs(stream)->oa_ctrl, 0); + xe_mmio_rmw32(mmio, __oa_regs(stream)->oa_ctrl, __oactrl_used_bits(stream), 0); if (xe_mmio_wait32(mmio, __oa_regs(stream)->oa_ctrl, OAG_OACONTROL_OA_COUNTER_ENABLE, 0, 50000, NULL, false)) drm_err(&stream->oa->xe->drm, @@ -2534,6 +2540,8 @@ static void __xe_oa_init_oa_units(struct xe_gt *gt) u->type = DRM_XE_OA_UNIT_TYPE_OAM; } + xe_mmio_write32(>->mmio, u->regs.oa_ctrl, 0); + /* Ensure MMIO trigger remains disabled till there is a stream */ xe_mmio_write32(>->mmio, u->regs.oa_debug, oag_configure_mmio_trigger(NULL, false)); -- cgit v1.2.3-59-g8ed1b From 367d7bc6d55a138cdcbd856e1e8f1f6967934954 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 13 Jan 2025 10:33:29 -0800 Subject: drm/i915/pmu: Remove i915_pmu_event_event_idx() perf event already has a default function that returns 0, no need to override with the same thing. Reviewed-by: Ashutosh Dixit Link: https://patchwork.freedesktop.org/patch/msgid/20250113183329.3138138-1-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/i915/i915_pmu.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index e55db036be1b..2eecd42f61ba 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -891,11 +891,6 @@ static void i915_pmu_event_del(struct perf_event *event, int flags) i915_pmu_event_stop(event, PERF_EF_UPDATE); } -static int i915_pmu_event_event_idx(struct perf_event *event) -{ - return 0; -} - struct i915_str_attribute { struct device_attribute attr; const char *str; @@ -1301,7 +1296,6 @@ void i915_pmu_register(struct drm_i915_private *i915) pmu->base.start = i915_pmu_event_start; pmu->base.stop = i915_pmu_event_stop; pmu->base.read = i915_pmu_event_read; - pmu->base.event_idx = i915_pmu_event_event_idx; ret = perf_pmu_register(&pmu->base, pmu->name, -1); if (ret) -- cgit v1.2.3-59-g8ed1b From 9ebb5846e1a3b1705f8a7cbc528888a1aa0b163e Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 21 Jan 2025 00:24:43 +0100 Subject: drm/xe/pf: Fix migration initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The migration support only needs to be initialized once, but it was incorrectly called from the xe_gt_sriov_pf_init_hw(), which is part of the reset flow and may be called multiple times. Fixes: d86e3737c7ab ("drm/xe/pf: Add functions to save and restore VF GuC state") Signed-off-by: Michal Wajdeczko Cc: Michał Winiarski Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250120232443.544-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt.c | 4 +++- drivers/gpu/drm/xe/xe_gt_sriov_pf.c | 14 +++++++++++++- drivers/gpu/drm/xe/xe_gt_sriov_pf.h | 6 ++++++ 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index b5c313a3e946..01a4a852b8f4 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -532,8 +532,10 @@ static int all_fw_domain_init(struct xe_gt *gt) if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) xe_lmtt_init_hw(>_to_tile(gt)->sriov.pf.lmtt); - if (IS_SRIOV_PF(gt_to_xe(gt))) + if (IS_SRIOV_PF(gt_to_xe(gt))) { + xe_gt_sriov_pf_init(gt); xe_gt_sriov_pf_init_hw(gt); + } xe_force_wake_put(gt_to_fw(gt), fw_ref); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c index e71fc3d2bda2..6f906c8e8108 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c @@ -68,6 +68,19 @@ int xe_gt_sriov_pf_init_early(struct xe_gt *gt) return 0; } +/** + * xe_gt_sriov_pf_init - Prepare SR-IOV PF data structures on PF. + * @gt: the &xe_gt to initialize + * + * Late one-time initialization of the PF data. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_pf_init(struct xe_gt *gt) +{ + return xe_gt_sriov_pf_migration_init(gt); +} + static bool pf_needs_enable_ggtt_guest_update(struct xe_device *xe) { return GRAPHICS_VERx100(xe) == 1200; @@ -90,7 +103,6 @@ void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) pf_enable_ggtt_guest_update(gt); xe_gt_sriov_pf_service_update(gt); - xe_gt_sriov_pf_migration_init(gt); } static u32 pf_get_vf_regs_stride(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf.h index 96fab779a906..f474509411c0 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.h @@ -10,6 +10,7 @@ struct xe_gt; #ifdef CONFIG_PCI_IOV int xe_gt_sriov_pf_init_early(struct xe_gt *gt); +int xe_gt_sriov_pf_init(struct xe_gt *gt); void xe_gt_sriov_pf_init_hw(struct xe_gt *gt); void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid); void xe_gt_sriov_pf_restart(struct xe_gt *gt); @@ -19,6 +20,11 @@ static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt) return 0; } +static inline int xe_gt_sriov_pf_init(struct xe_gt *gt) +{ + return 0; +} + static inline void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) { } -- cgit v1.2.3-59-g8ed1b From 5994018ecffc9e70e192bede2270819d8c93b2d4 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 21 Jan 2025 10:48:32 +0100 Subject: drm/xe/guc: Fix sizeof(32) typo A small typo leads to the following static code checker warning: drivers/gpu/drm/xe/xe_guc_buf.c:81 xe_guc_buf_reserve() warn: sizeof(NUMBER)? Reported-by: Dan Carpenter Closes: https://lore.kernel.org/intel-xe/0d5bcbf1-79f9-4a10-a221-ddbaec9f6122@stanley.mountain/ Fixes: 696bfdf273ea ("drm/xe/guc: Introduce the GuC Buffer Cache") Signed-off-by: Michal Wajdeczko Cc: Dan Carpenter Cc: Matthew Brost Reviewed-by: Stuart Summers Link: https://patchwork.freedesktop.org/patch/msgid/20250121094832.588-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc_buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c index ce6d9830e13b..0193c94dd6a0 100644 --- a/drivers/gpu/drm/xe/xe_guc_buf.c +++ b/drivers/gpu/drm/xe/xe_guc_buf.c @@ -78,7 +78,7 @@ struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords) struct drm_suballoc *sa; if (cache->sam) - sa = __xe_sa_bo_new(cache->sam, dwords * sizeof(32), GFP_ATOMIC); + sa = __xe_sa_bo_new(cache->sam, dwords * sizeof(u32), GFP_ATOMIC); else sa = ERR_PTR(-EOPNOTSUPP); -- cgit v1.2.3-59-g8ed1b From 6f71507415841d1a6d38118e5fa0eaf0caab9c17 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 21 Jan 2025 06:52:03 -0800 Subject: drm/i915/backlight: Return immediately when scale() finds invalid parameters The scale() functions detects invalid parameters, but continues its calculations anyway. This causes bad results if negative values are used for unsigned operations. Worst case, a division by 0 error will be seen if source_min == source_max. On top of that, after v6.13, the sequence of WARN_ON() followed by clamp() may result in a build error with gcc 13.x. drivers/gpu/drm/i915/display/intel_backlight.c: In function 'scale': include/linux/compiler_types.h:542:45: error: call to '__compiletime_assert_415' declared with attribute error: clamp() low limit source_min greater than high limit source_max This happens if the compiler decides to rearrange the code as follows. if (source_min > source_max) { WARN(..); /* Do the clamp() knowing that source_min > source_max */ source_val = clamp(source_val, source_min, source_max); } else { /* Do the clamp knowing that source_min <= source_max */ source_val = clamp(source_val, source_min, source_max); } Fix the problem by evaluating the return values from WARN_ON and returning immediately after a warning. While at it, fix divide by zero error seen if source_min == source_max. Analyzed-by: Linus Torvalds Suggested-by: Linus Torvalds Suggested-by: David Laight Cc: David Laight Cc: Jani Nikula Cc: Andy Shevchenko Signed-off-by: Guenter Roeck Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250121145203.2851237-1-linux@roeck-us.net Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_backlight.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index fc1e517e074a..7e6ce905bdaf 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -41,8 +41,9 @@ static u32 scale(u32 source_val, { u64 target_val; - WARN_ON(source_min > source_max); - WARN_ON(target_min > target_max); + if (WARN_ON(source_min >= source_max) || + WARN_ON(target_min > target_max)) + return target_min; /* defensive */ source_val = clamp(source_val, source_min, source_max); -- cgit v1.2.3-59-g8ed1b From c132ec36fc28d58ba7e28b0f66651a9310e0d61a Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 17 Jan 2025 10:37:13 +0530 Subject: drm/i915/dp: Correct max compressed bpp bounds by using link bpp While setting the bounds for compressed bpp, we ensure that the compressed bpp is less than the pipe bpp. This causes an issue with the 420 output format, where the effective link bpp (or output bpp) is half that of the pipe bpp. Therefore instead of using pipe bpp, use the output bpp to set the bounds for the compressed bpp. v2: Use identifier output_bpp instead of link_bpp (Imre) Signed-off-by: Ankit Nautiyal Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250117050713.152012-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f1f3b1bb1e89..9ec23860b593 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2068,9 +2068,10 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, int timeslots) { int i, ret; + int output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); /* Compressed BPP should be less than the Input DSC bpp */ - dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1); + dsc_max_bpp = min(dsc_max_bpp, output_bpp - 1); for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) { if (valid_dsc_bpp[i] < dsc_min_bpp) @@ -2111,6 +2112,7 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, { struct intel_display *display = to_intel_display(intel_dp); u8 bppx16_incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd); + int output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); u16 compressed_bppx16; u8 bppx16_step; int ret; @@ -2121,7 +2123,7 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, bppx16_step = 16 / bppx16_incr; /* Compressed BPP should be less than the Input DSC bpp */ - dsc_max_bpp = min(dsc_max_bpp << 4, (pipe_bpp << 4) - bppx16_step); + dsc_max_bpp = min(dsc_max_bpp << 4, (output_bpp << 4) - bppx16_step); dsc_min_bpp = dsc_min_bpp << 4; for (compressed_bppx16 = dsc_max_bpp; -- cgit v1.2.3-59-g8ed1b From 3d09b2718969f6db5b9e50daa9a033a78f065522 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:06 +0100 Subject: drm/ast: Detect wide-screen support before creating modeset pipeline Wide-screen support is relevant for mode validation. Do not detect it before setting up the mode-setting pipeline. Gets the function call out of the way of other initialization code. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index bc37c65305d4..037d389ab630 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -290,7 +290,6 @@ struct drm_device *ast_device_create(struct pci_dev *pdev, ast->regs = regs; ast->ioregs = ioregs; - ast_detect_widescreen(ast); ast_detect_tx_chip(ast, need_post); ret = ast_get_dram_info(ast); @@ -315,6 +314,8 @@ struct drm_device *ast_device_create(struct pci_dev *pdev, drm_info(dev, "failed to map reserved buffer!\n"); } + ast_detect_widescreen(ast); + ret = ast_mode_config_init(ast); if (ret) return ERR_PTR(ret); -- cgit v1.2.3-59-g8ed1b From be1c00b180f1c580c93e585058e64df51fcfd4c2 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:07 +0100 Subject: drm/ast: Detect DRAM before TX-chip Move DRAM detection before TX-chip detection. Both steps are independent from each other. Detection of the TX-chip is now next to posting those chips, which can be done in a single step. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 037d389ab630..456230bef273 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -290,15 +290,13 @@ struct drm_device *ast_device_create(struct pci_dev *pdev, ast->regs = regs; ast->ioregs = ioregs; - ast_detect_tx_chip(ast, need_post); - ret = ast_get_dram_info(ast); if (ret) return ERR_PTR(ret); - drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n", ast->mclk, ast->dram_type, ast->dram_bus_width); + ast_detect_tx_chip(ast, need_post); if (need_post) ast_post_gpu(ast); -- cgit v1.2.3-59-g8ed1b From b40e209130bff435c8dcd17660cb4614ae62a3fb Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:08 +0100 Subject: drm/ast: Refactor ast_post_gpu() by Gen Reorganize ast_post_gpu() so that it first branches by Gen and then by config mode and TX chip. This will later make it possible to split up the function by Gen. The helper ast_init_3rdtx() only handles Gen4 and Gen5, so leave it out from the other Gens. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_post.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 364030f97571..49f661760f9e 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -344,21 +344,37 @@ void ast_post_gpu(struct ast_device *ast) { ast_set_def_ext_reg(ast); - if (IS_AST_GEN7(ast)) { + if (AST_GEN(ast) >= 7) { if (ast->tx_chip == AST_TX_ASTDP) ast_dp_launch(ast); - } else if (ast->config_mode == ast_use_p2a) { - if (IS_AST_GEN6(ast)) + } else if (AST_GEN(ast) >= 6) { + if (ast->config_mode == ast_use_p2a) { ast_post_chip_2500(ast); - else if (IS_AST_GEN5(ast) || IS_AST_GEN4(ast)) + } else { + if (ast->tx_chip == AST_TX_SIL164) { + /* Enable DVO */ + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); + } + } + } else if (AST_GEN(ast) >= 4) { + if (ast->config_mode == ast_use_p2a) { ast_post_chip_2300(ast); - else + ast_init_3rdtx(ast); + } else { + if (ast->tx_chip == AST_TX_SIL164) { + /* Enable DVO */ + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); + } + } + } else { + if (ast->config_mode == ast_use_p2a) { ast_init_dram_reg(ast); - - ast_init_3rdtx(ast); - } else { - if (ast->tx_chip == AST_TX_SIL164) - ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); /* Enable DVO */ + } else { + if (ast->tx_chip == AST_TX_SIL164) { + /* Enable DVO */ + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); + } + } } } -- cgit v1.2.3-59-g8ed1b From 1c6220a3950bd8e60126f5ea234f3f7bd86321b1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:09 +0100 Subject: drm/ast: Initialize ASTDP in ast_post_gpu() Remove the call to ast_dp_launch() from ast_detect_tx_chip() and perform it unconditionally in ast_post_gpu(). Also add error handling: the detection code apparently used ast_dp_launch() to test for a working ASTDP, falling back to VGA on errors. As the VBIOS reports ASTDP, silently ignoring errors is questionable behavior. With the refactoring, failing to initialize the ASTDP will also fail probing the driver. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.c | 6 +++++- drivers/gpu/drm/ast/ast_drv.h | 2 +- drivers/gpu/drm/ast/ast_main.c | 19 +++++++++++++------ drivers/gpu/drm/ast/ast_post.c | 13 ++++++++++--- 4 files changed, 29 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index ff3bcdd1cff2..cddd69972e89 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -393,11 +393,15 @@ static int ast_drm_freeze(struct drm_device *dev) static int ast_drm_thaw(struct drm_device *dev) { struct ast_device *ast = to_ast_device(dev); + int ret; ast_enable_vga(ast->ioregs); ast_open_key(ast->ioregs); ast_enable_mmio(dev->dev, ast->ioregs); - ast_post_gpu(ast); + + ret = ast_post_gpu(ast); + if (ret) + return ret; return drm_mode_config_helper_resume(dev); } diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 6b4305ac07d4..cf9edef8fca6 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -445,7 +445,7 @@ int ast_mode_config_init(struct ast_device *ast); int ast_mm_init(struct ast_device *ast); /* ast post */ -void ast_post_gpu(struct ast_device *ast); +int ast_post_gpu(struct ast_device *ast); u32 ast_mindwm(struct ast_device *ast, u32 r); void ast_moutdwm(struct ast_device *ast, u32 r, u32 v); void ast_patch_ahb_2500(void __iomem *regs); diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 456230bef273..474eb255b325 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -138,10 +138,7 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) } else if (IS_AST_GEN7(ast)) { if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, AST_IO_VGACRD1_TX_TYPE_MASK) == AST_IO_VGACRD1_TX_ASTDP) { - int ret = ast_dp_launch(ast); - - if (!ret) - ast->tx_chip = AST_TX_ASTDP; + ast->tx_chip = AST_TX_ASTDP; } } @@ -297,8 +294,18 @@ struct drm_device *ast_device_create(struct pci_dev *pdev, ast->mclk, ast->dram_type, ast->dram_bus_width); ast_detect_tx_chip(ast, need_post); - if (need_post) - ast_post_gpu(ast); + switch (ast->tx_chip) { + case AST_TX_ASTDP: + ret = ast_post_gpu(ast); + break; + default: + ret = 0; + if (need_post) + ret = ast_post_gpu(ast); + break; + } + if (ret) + return ERR_PTR(ret); ret = ast_mm_init(ast); if (ret) diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 49f661760f9e..0daa8e52a092 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -340,13 +340,18 @@ static void ast_init_dram_reg(struct ast_device *ast) } while ((j & 0x40) == 0); } -void ast_post_gpu(struct ast_device *ast) +int ast_post_gpu(struct ast_device *ast) { + int ret; + ast_set_def_ext_reg(ast); if (AST_GEN(ast) >= 7) { - if (ast->tx_chip == AST_TX_ASTDP) - ast_dp_launch(ast); + if (ast->tx_chip == AST_TX_ASTDP) { + ret = ast_dp_launch(ast); + if (ret) + return ret; + } } else if (AST_GEN(ast) >= 6) { if (ast->config_mode == ast_use_p2a) { ast_post_chip_2500(ast); @@ -376,6 +381,8 @@ void ast_post_gpu(struct ast_device *ast) } } } + + return 0; } /* AST 2300 DRAM settings */ -- cgit v1.2.3-59-g8ed1b From 87478ba50a05a1f44508316ae109622e8a85adc9 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:10 +0100 Subject: drm/ast: Hide Gens 1 to 3 TX detection in branch Gen7 only supports ASTDP. Gens 4 to 6 support various TX chips, except ASTDP. These boards detect the TX chips by reading the SoC scratch register as VGACRD1. Gens 1 to 3 only support SIL164. These boards read the DVO bit from VGACRA3. Hence move this test behind a branch, so that it does not run on later generations. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-6-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 474eb255b325..50b57bc15d53 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -96,21 +96,21 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) /* Check 3rd Tx option (digital output afaik) */ ast->tx_chip = AST_TX_NONE; - /* - * VGACRA3 Enhanced Color Mode Register, check if DVO is already - * enabled, in that case, assume we have a SIL164 TMDS transmitter - * - * Don't make that assumption if we the chip wasn't enabled and - * is at power-on reset, otherwise we'll incorrectly "detect" a - * SIL164 when there is none. - */ - if (!need_post) { - jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); - if (jreg & 0x80) - ast->tx_chip = AST_TX_SIL164; - } - - if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { + if (AST_GEN(ast) <= 3) { + /* + * VGACRA3 Enhanced Color Mode Register, check if DVO is already + * enabled, in that case, assume we have a SIL164 TMDS transmitter + * + * Don't make that assumption if we the chip wasn't enabled and + * is at power-on reset, otherwise we'll incorrectly "detect" a + * SIL164 when there is none. + */ + if (!need_post) { + jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); + if (jreg & 0x80) + ast->tx_chip = AST_TX_SIL164; + } + } else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { /* * On AST GEN4+, look the configuration set by the SoC in * the SOC scratch register #1 bits 11:8 (interestingly marked -- cgit v1.2.3-59-g8ed1b From 2eede6f1d2b1d3c36e77555f7b98ab8a45f0527c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:11 +0100 Subject: drm/ast: Align Gen1 DVO detection to register manual Align variable names and register constants for TX-chip detection to the names in the register manual. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 6 +++--- drivers/gpu/drm/ast/ast_reg.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 50b57bc15d53..40d3b7770cf1 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -76,7 +76,7 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) }; struct drm_device *dev = &ast->base; - u8 jreg, vgacrd1; + u8 vgacra3, vgacrd1; /* * Several of the listed TX chips are not explicitly supported @@ -106,8 +106,8 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) * SIL164 when there is none. */ if (!need_post) { - jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); - if (jreg & 0x80) + vgacra3 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); + if (vgacra3 & AST_IO_VGACRA3_DVO_ENABLED) ast->tx_chip = AST_TX_SIL164; } } else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { diff --git a/drivers/gpu/drm/ast/ast_reg.h b/drivers/gpu/drm/ast/ast_reg.h index 2aadf07d135a..0745d58e5b45 100644 --- a/drivers/gpu/drm/ast/ast_reg.h +++ b/drivers/gpu/drm/ast/ast_reg.h @@ -32,6 +32,7 @@ #define AST_IO_VGACR80_PASSWORD (0xa8) #define AST_IO_VGACRA1_VGAIO_DISABLED BIT(1) #define AST_IO_VGACRA1_MMIO_ENABLED BIT(2) +#define AST_IO_VGACRA3_DVO_ENABLED BIT(7) #define AST_IO_VGACRB6_HSYNC_OFF BIT(0) #define AST_IO_VGACRB6_VSYNC_OFF BIT(1) #define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ -- cgit v1.2.3-59-g8ed1b From dc80fde7947fd9d90d229e2b007cda2066943fb7 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:12 +0100 Subject: drm/ast: Merge TX-chip detection code for Gen4 and later Gens 4 to 6 and Gen7 use the same pattern for detecting the installed TX chips. Merge the code into a single branch. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-8-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 40d3b7770cf1..b0d1b99ed532 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -110,15 +110,18 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) if (vgacra3 & AST_IO_VGACRA3_DVO_ENABLED) ast->tx_chip = AST_TX_SIL164; } - } else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { + } else { /* - * On AST GEN4+, look the configuration set by the SoC in + * On AST GEN4+, look at the configuration set by the SoC in * the SOC scratch register #1 bits 11:8 (interestingly marked * as "reserved" in the spec) */ jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, AST_IO_VGACRD1_TX_TYPE_MASK); switch (jreg) { + /* + * GEN4 to GEN6 + */ case AST_IO_VGACRD1_TX_SIL164_VBIOS: ast->tx_chip = AST_TX_SIL164; break; @@ -134,11 +137,13 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) fallthrough; case AST_IO_VGACRD1_TX_FW_EMBEDDED_FW: ast->tx_chip = AST_TX_DP501; - } - } else if (IS_AST_GEN7(ast)) { - if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, AST_IO_VGACRD1_TX_TYPE_MASK) == - AST_IO_VGACRD1_TX_ASTDP) { + break; + /* + * GEN7+ + */ + case AST_IO_VGACRD1_TX_ASTDP: ast->tx_chip = AST_TX_ASTDP; + break; } } -- cgit v1.2.3-59-g8ed1b From a9301e5bef12f8989a02d886109f13e89e1e51b0 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Jan 2025 11:29:13 +0100 Subject: drm/ast: Only warn about unsupported TX chips on Gen4 and later Only Gen4 and later read the installed TX chip from the SoC. So only warn on those generations about unsupported chips. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-9-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index b0d1b99ed532..ba69280b33e7 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -78,21 +78,6 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) struct drm_device *dev = &ast->base; u8 vgacra3, vgacrd1; - /* - * Several of the listed TX chips are not explicitly supported - * by the ast driver. If these exist in real-world devices, they - * are most likely reported as VGA or SIL164 outputs. We warn here - * to get bug reports for these devices. If none come in for some - * time, we can begin to fail device probing on these values. - */ - vgacrd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, AST_IO_VGACRD1_TX_TYPE_MASK); - drm_WARN(dev, vgacrd1 == AST_IO_VGACRD1_TX_ITE66121_VBIOS, - "ITE IT66121 detected, 0x%x, Gen%lu\n", vgacrd1, AST_GEN(ast)); - drm_WARN(dev, vgacrd1 == AST_IO_VGACRD1_TX_CH7003_VBIOS, - "Chrontel CH7003 detected, 0x%x, Gen%lu\n", vgacrd1, AST_GEN(ast)); - drm_WARN(dev, vgacrd1 == AST_IO_VGACRD1_TX_ANX9807_VBIOS, - "Analogix ANX9807 detected, 0x%x, Gen%lu\n", vgacrd1, AST_GEN(ast)); - /* Check 3rd Tx option (digital output afaik) */ ast->tx_chip = AST_TX_NONE; @@ -116,9 +101,9 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) * the SOC scratch register #1 bits 11:8 (interestingly marked * as "reserved" in the spec) */ - jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, - AST_IO_VGACRD1_TX_TYPE_MASK); - switch (jreg) { + vgacrd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, + AST_IO_VGACRD1_TX_TYPE_MASK); + switch (vgacrd1) { /* * GEN4 to GEN6 */ @@ -144,6 +129,25 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) case AST_IO_VGACRD1_TX_ASTDP: ast->tx_chip = AST_TX_ASTDP; break; + /* + * Several of the listed TX chips are not explicitly supported + * by the ast driver. If these exist in real-world devices, they + * are most likely reported as VGA or SIL164 outputs. We warn here + * to get bug reports for these devices. If none come in for some + * time, we can begin to fail device probing on these values. + */ + case AST_IO_VGACRD1_TX_ITE66121_VBIOS: + drm_warn(dev, "ITE IT66121 detected, 0x%x, Gen%lu\n", + vgacrd1, AST_GEN(ast)); + break; + case AST_IO_VGACRD1_TX_CH7003_VBIOS: + drm_warn(dev, "Chrontel CH7003 detected, 0x%x, Gen%lu\n", + vgacrd1, AST_GEN(ast)); + break; + case AST_IO_VGACRD1_TX_ANX9807_VBIOS: + drm_warn(dev, "Analogix ANX9807 detected, 0x%x, Gen%lu\n", + vgacrd1, AST_GEN(ast)); + break; } } -- cgit v1.2.3-59-g8ed1b From 1abf834951fb039f24819283b7abd9f8309852b0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 8 Jan 2025 17:19:12 +0200 Subject: drm/i915/dp_mst: Fix error handling while adding a connector After an error during adding an MST connector the MST port and the intel_connector object could be leaked, fix this up. Reviewed-by: Rodrigo Vivi Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250108151916.491113-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 0c44fc7dd86c..85aafdf573e8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1717,11 +1717,8 @@ mst_topology_add_connector(struct drm_dp_mst_topology_mgr *mgr, ret = drm_connector_dynamic_init(display->drm, connector, &mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort, NULL); - if (ret) { - drm_dp_mst_put_port_malloc(port); - intel_connector_free(intel_connector); - return NULL; - } + if (ret) + goto err_put_port; intel_connector->dp.dsc_decompression_aux = drm_dp_mst_dsc_aux_for_port(port); intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector); @@ -1736,12 +1733,12 @@ mst_topology_add_connector(struct drm_dp_mst_topology_mgr *mgr, ret = drm_connector_attach_encoder(&intel_connector->base, enc); if (ret) - goto err; + goto err_cleanup_connector; } ret = mst_topology_add_connector_properties(intel_dp, connector, pathprop); if (ret) - goto err; + goto err_cleanup_connector; ret = intel_dp_hdcp_init(dig_port, intel_connector); if (ret) @@ -1750,8 +1747,12 @@ mst_topology_add_connector(struct drm_dp_mst_topology_mgr *mgr, return connector; -err: +err_cleanup_connector: drm_connector_cleanup(connector); +err_put_port: + drm_dp_mst_put_port_malloc(port); + intel_connector_free(intel_connector); + return NULL; } -- cgit v1.2.3-59-g8ed1b From d49b485d1be3cb1b3b719cf4031f879dbc26c633 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 8 Jan 2025 17:19:13 +0200 Subject: drm/i915/dp_mst: Use intel_connector vs. drm_connector pointer in intel_dp_mst.c Follow the canonical way in intel_dp_mst.c, referencing a connector only via a struct intel_connector pointer and naming this pointer 'connector' instead of 'intel_connector', the only exception being the casting of a drm_connector function parameter pointer to intel_connector, calling the drm_connector pointer _connector. Suggested-by: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250108151916.491113-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 180 ++++++++++++++-------------- 1 file changed, 88 insertions(+), 92 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 85aafdf573e8..c4da16631d43 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -943,33 +943,32 @@ mst_connector_atomic_topology_check(struct intel_connector *connector, } static int -mst_connector_atomic_check(struct drm_connector *connector, +mst_connector_atomic_check(struct drm_connector *_connector, struct drm_atomic_state *_state) { struct intel_atomic_state *state = to_intel_atomic_state(_state); - struct intel_connector *intel_connector = - to_intel_connector(connector); + struct intel_connector *connector = to_intel_connector(_connector); int ret; - ret = intel_digital_connector_atomic_check(connector, &state->base); + ret = intel_digital_connector_atomic_check(&connector->base, &state->base); if (ret) return ret; - ret = mst_connector_atomic_topology_check(intel_connector, state); + ret = mst_connector_atomic_topology_check(connector, state); if (ret) return ret; - if (intel_connector_needs_modeset(state, connector)) { + if (intel_connector_needs_modeset(state, &connector->base)) { ret = intel_dp_tunnel_atomic_check_state(state, - intel_connector->mst_port, - intel_connector); + connector->mst_port, + connector); if (ret) return ret; } return drm_dp_atomic_release_time_slots(&state->base, - &intel_connector->mst_port->mst_mgr, - intel_connector->port); + &connector->mst_port->mst_mgr, + connector->port); } static void mst_stream_disable(struct intel_atomic_state *state, @@ -1349,23 +1348,23 @@ static bool mst_stream_initial_fastset_check(struct intel_encoder *encoder, return intel_dp_initial_fastset_check(primary_encoder, crtc_state); } -static int mst_connector_get_ddc_modes(struct drm_connector *connector) +static int mst_connector_get_ddc_modes(struct drm_connector *_connector) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_connector *intel_connector = to_intel_connector(connector); - struct intel_dp *intel_dp = intel_connector->mst_port; + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector->base.dev); + struct intel_dp *intel_dp = connector->mst_port; const struct drm_edid *drm_edid; int ret; - if (drm_connector_is_unregistered(connector)) - return intel_connector_update_modes(connector, NULL); + if (drm_connector_is_unregistered(&connector->base)) + return intel_connector_update_modes(&connector->base, NULL); if (!intel_display_driver_check_access(display)) - return drm_edid_connector_add_modes(connector); + return drm_edid_connector_add_modes(&connector->base); - drm_edid = drm_dp_mst_edid_read(connector, &intel_dp->mst_mgr, intel_connector->port); + drm_edid = drm_dp_mst_edid_read(&connector->base, &intel_dp->mst_mgr, connector->port); - ret = intel_connector_update_modes(connector, drm_edid); + ret = intel_connector_update_modes(&connector->base, drm_edid); drm_edid_free(drm_edid); @@ -1373,32 +1372,29 @@ static int mst_connector_get_ddc_modes(struct drm_connector *connector) } static int -mst_connector_late_register(struct drm_connector *connector) +mst_connector_late_register(struct drm_connector *_connector) { - struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_connector *connector = to_intel_connector(_connector); int ret; - ret = drm_dp_mst_connector_late_register(connector, - intel_connector->port); + ret = drm_dp_mst_connector_late_register(&connector->base, connector->port); if (ret < 0) return ret; - ret = intel_connector_register(connector); + ret = intel_connector_register(&connector->base); if (ret < 0) - drm_dp_mst_connector_early_unregister(connector, - intel_connector->port); + drm_dp_mst_connector_early_unregister(&connector->base, connector->port); return ret; } static void -mst_connector_early_unregister(struct drm_connector *connector) +mst_connector_early_unregister(struct drm_connector *_connector) { - struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_connector *connector = to_intel_connector(_connector); - intel_connector_unregister(connector); - drm_dp_mst_connector_early_unregister(connector, - intel_connector->port); + intel_connector_unregister(&connector->base); + drm_dp_mst_connector_early_unregister(&connector->base, connector->port); } static const struct drm_connector_funcs mst_connector_funcs = { @@ -1412,23 +1408,25 @@ static const struct drm_connector_funcs mst_connector_funcs = { .atomic_duplicate_state = intel_digital_connector_duplicate_state, }; -static int mst_connector_get_modes(struct drm_connector *connector) +static int mst_connector_get_modes(struct drm_connector *_connector) { - return mst_connector_get_ddc_modes(connector); + struct intel_connector *connector = to_intel_connector(_connector); + + return mst_connector_get_ddc_modes(&connector->base); } static int -mst_connector_mode_valid_ctx(struct drm_connector *connector, +mst_connector_mode_valid_ctx(struct drm_connector *_connector, struct drm_display_mode *mode, struct drm_modeset_acquire_ctx *ctx, enum drm_mode_status *status) { - struct intel_display *display = to_intel_display(connector->dev); - struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_connector *intel_connector = to_intel_connector(connector); - struct intel_dp *intel_dp = intel_connector->mst_port; + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector->base.dev); + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_dp *intel_dp = connector->mst_port; struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr; - struct drm_dp_mst_port *port = intel_connector->port; + struct drm_dp_mst_port *port = connector->port; const int min_bpp = 18; int max_dotclk = display->cdclk.max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; @@ -1439,7 +1437,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector, int target_clock = mode->clock; int num_joined_pipes; - if (drm_connector_is_unregistered(connector)) { + if (drm_connector_is_unregistered(&connector->base)) { *status = MODE_ERROR; return 0; } @@ -1477,7 +1475,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector, * corresponding link capabilities of the sink) in case the * stream is uncompressed for it by the last branch device. */ - num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, intel_connector, + num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector, mode->hdisplay, target_clock); max_dotclk *= num_joined_pipes; @@ -1491,14 +1489,14 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector, return 0; } - if (intel_dp_has_dsc(intel_connector)) { + if (intel_dp_has_dsc(connector)) { /* * TBD pass the connector BPC, * for now U8_MAX so that max BPC on that platform would be picked */ - int pipe_bpp = intel_dp_dsc_compute_max_bpp(intel_connector, U8_MAX); + int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX); - if (drm_dp_sink_supports_fec(intel_connector->dp.fec_capability)) { + if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) { dsc_max_compressed_bpp = intel_dp_dsc_get_max_compressed_bpp(display, max_link_clock, @@ -1509,7 +1507,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector, INTEL_OUTPUT_FORMAT_RGB, pipe_bpp, 64); dsc_slice_count = - intel_dp_dsc_get_slice_count(intel_connector, + intel_dp_dsc_get_slice_count(connector, target_clock, mode->hdisplay, num_joined_pipes); @@ -1533,39 +1531,39 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector, } static struct drm_encoder * -mst_connector_atomic_best_encoder(struct drm_connector *connector, +mst_connector_atomic_best_encoder(struct drm_connector *_connector, struct drm_atomic_state *state) { - struct drm_connector_state *connector_state = drm_atomic_get_new_connector_state(state, - connector); - struct intel_connector *intel_connector = to_intel_connector(connector); - struct intel_dp *intel_dp = intel_connector->mst_port; + struct intel_connector *connector = to_intel_connector(_connector); + struct drm_connector_state *connector_state = + drm_atomic_get_new_connector_state(state, &connector->base); + struct intel_dp *intel_dp = connector->mst_port; struct intel_crtc *crtc = to_intel_crtc(connector_state->crtc); return &intel_dp->mst_encoders[crtc->pipe]->base.base; } static int -mst_connector_detect_ctx(struct drm_connector *connector, +mst_connector_detect_ctx(struct drm_connector *_connector, struct drm_modeset_acquire_ctx *ctx, bool force) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_connector *intel_connector = to_intel_connector(connector); - struct intel_dp *intel_dp = intel_connector->mst_port; + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector->base.dev); + struct intel_dp *intel_dp = connector->mst_port; if (!intel_display_device_enabled(display)) return connector_status_disconnected; - if (drm_connector_is_unregistered(connector)) + if (drm_connector_is_unregistered(&connector->base)) return connector_status_disconnected; if (!intel_display_driver_check_access(display)) - return connector->status; + return connector->base.status; - intel_dp_flush_connector_commits(intel_connector); + intel_dp_flush_connector_commits(connector); - return drm_dp_mst_detect_port(connector, ctx, &intel_dp->mst_mgr, - intel_connector->port); + return drm_dp_mst_detect_port(&connector->base, ctx, &intel_dp->mst_mgr, + connector->port); } static const struct drm_connector_helper_funcs mst_connector_helper_funcs = { @@ -1601,29 +1599,30 @@ static bool mst_connector_get_hw_state(struct intel_connector *connector) } static int mst_topology_add_connector_properties(struct intel_dp *intel_dp, - struct drm_connector *connector, + struct drm_connector *_connector, const char *pathprop) { struct intel_display *display = to_intel_display(intel_dp); + struct intel_connector *connector = to_intel_connector(_connector); - drm_object_attach_property(&connector->base, + drm_object_attach_property(&connector->base.base, display->drm->mode_config.path_property, 0); - drm_object_attach_property(&connector->base, + drm_object_attach_property(&connector->base.base, display->drm->mode_config.tile_property, 0); - intel_attach_force_audio_property(connector); - intel_attach_broadcast_rgb_property(connector); + intel_attach_force_audio_property(&connector->base); + intel_attach_broadcast_rgb_property(&connector->base); /* * Reuse the prop from the SST connector because we're * not allowed to create new props after device registration. */ - connector->max_bpc_property = + connector->base.max_bpc_property = intel_dp->attached_connector->base.max_bpc_property; - if (connector->max_bpc_property) - drm_connector_attach_max_bpc_property(connector, 6, 12); + if (connector->base.max_bpc_property) + drm_connector_attach_max_bpc_property(&connector->base, 6, 12); - return drm_connector_set_path_property(connector, pathprop); + return drm_connector_set_path_property(&connector->base, pathprop); } static void @@ -1696,62 +1695,59 @@ mst_topology_add_connector(struct drm_dp_mst_topology_mgr *mgr, struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr); struct intel_display *display = to_intel_display(intel_dp); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct intel_connector *intel_connector; - struct drm_connector *connector; + struct intel_connector *connector; enum pipe pipe; int ret; - intel_connector = intel_connector_alloc(); - if (!intel_connector) + connector = intel_connector_alloc(); + if (!connector) return NULL; - connector = &intel_connector->base; - - intel_connector->get_hw_state = mst_connector_get_hw_state; - intel_connector->sync_state = intel_dp_connector_sync_state; - intel_connector->mst_port = intel_dp; - intel_connector->port = port; + connector->get_hw_state = mst_connector_get_hw_state; + connector->sync_state = intel_dp_connector_sync_state; + connector->mst_port = intel_dp; + connector->port = port; drm_dp_mst_get_port_malloc(port); - intel_dp_init_modeset_retry_work(intel_connector); + intel_dp_init_modeset_retry_work(connector); - ret = drm_connector_dynamic_init(display->drm, connector, &mst_connector_funcs, + ret = drm_connector_dynamic_init(display->drm, &connector->base, &mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort, NULL); if (ret) goto err_put_port; - intel_connector->dp.dsc_decompression_aux = drm_dp_mst_dsc_aux_for_port(port); - intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector); - intel_connector->dp.dsc_hblank_expansion_quirk = - detect_dsc_hblank_expansion_quirk(intel_connector); + connector->dp.dsc_decompression_aux = drm_dp_mst_dsc_aux_for_port(port); + intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, connector); + connector->dp.dsc_hblank_expansion_quirk = + detect_dsc_hblank_expansion_quirk(connector); - drm_connector_helper_add(connector, &mst_connector_helper_funcs); + drm_connector_helper_add(&connector->base, &mst_connector_helper_funcs); for_each_pipe(display, pipe) { struct drm_encoder *enc = &intel_dp->mst_encoders[pipe]->base.base; - ret = drm_connector_attach_encoder(&intel_connector->base, enc); + ret = drm_connector_attach_encoder(&connector->base, enc); if (ret) goto err_cleanup_connector; } - ret = mst_topology_add_connector_properties(intel_dp, connector, pathprop); + ret = mst_topology_add_connector_properties(intel_dp, &connector->base, pathprop); if (ret) goto err_cleanup_connector; - ret = intel_dp_hdcp_init(dig_port, intel_connector); + ret = intel_dp_hdcp_init(dig_port, connector); if (ret) drm_dbg_kms(display->drm, "[%s:%d] HDCP MST init failed, skipping.\n", - connector->name, connector->base.id); + connector->base.name, connector->base.base.id); - return connector; + return &connector->base; err_cleanup_connector: - drm_connector_cleanup(connector); + drm_connector_cleanup(&connector->base); err_put_port: drm_dp_mst_put_port_malloc(port); - intel_connector_free(intel_connector); + intel_connector_free(connector); return NULL; } -- cgit v1.2.3-59-g8ed1b From ae1e7fba27c9f68dfcaa0f527ee38dda013e566c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 8 Jan 2025 17:19:14 +0200 Subject: drm/i915/dp_mst: Simplify using to_intel_display() passing it an intel_connector pointer Simplify the use of to_intel_display() in intel_dp_mst.c passing it the already available intel_connector pointer, instead of looking up a drm_device pointer for the same purpose. Suggested-by: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250108151916.491113-4-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index c4da16631d43..84538aa695c2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1351,7 +1351,7 @@ static bool mst_stream_initial_fastset_check(struct intel_encoder *encoder, static int mst_connector_get_ddc_modes(struct drm_connector *_connector) { struct intel_connector *connector = to_intel_connector(_connector); - struct intel_display *display = to_intel_display(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_dp *intel_dp = connector->mst_port; const struct drm_edid *drm_edid; int ret; @@ -1422,7 +1422,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector, enum drm_mode_status *status) { struct intel_connector *connector = to_intel_connector(_connector); - struct intel_display *display = to_intel_display(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_dp *intel_dp = connector->mst_port; struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr; @@ -1548,7 +1548,7 @@ mst_connector_detect_ctx(struct drm_connector *_connector, struct drm_modeset_acquire_ctx *ctx, bool force) { struct intel_connector *connector = to_intel_connector(_connector); - struct intel_display *display = to_intel_display(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_dp *intel_dp = connector->mst_port; if (!intel_display_device_enabled(display)) -- cgit v1.2.3-59-g8ed1b From 6aeaa55ae7683f7046fa362d57788f7fc1111e47 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 8 Jan 2025 17:19:15 +0200 Subject: drm/i915/dp_mst: Simplify getting a drm_device pointer needed by to_i915() Simplify getting a drm_device pointer when using to_i915() in intel_dp_mst.c from the already available intel_display object, instead of getting it from a DRM KMS object. While at it rename dev_priv to i915, following the driver's standard terminology. Suggested-by: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250108151916.491113-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 84538aa695c2..afc843fd5393 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1423,7 +1423,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector, { struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(display->drm); struct intel_dp *intel_dp = connector->mst_port; struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr; struct drm_dp_mst_port *port = connector->port; @@ -1442,7 +1442,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector, return 0; } - *status = intel_cpu_transcoder_mode_valid(dev_priv, mode); + *status = intel_cpu_transcoder_mode_valid(i915, mode); if (*status != MODE_OK) return 0; @@ -1526,7 +1526,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector, return 0; } - *status = intel_mode_valid_max_plane_size(dev_priv, mode, num_joined_pipes); + *status = intel_mode_valid_max_plane_size(i915, mode, num_joined_pipes); return 0; } -- cgit v1.2.3-59-g8ed1b From b9360d1751ec9397ab9e4fdea24a749d8fc19c91 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 8 Jan 2025 17:19:16 +0200 Subject: drm/i915/dp_mst: Use intel_display::platform.alderlake_p instead of IS_ALDERLAKE_P() Use the driver's standard intel_display::platform.alderlake_p instead of IS_ALDERLAKE_P(). Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250108151916.491113-6-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index afc843fd5393..fbfc756368b8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1219,11 +1219,10 @@ static void mst_stream_pre_enable(struct intel_atomic_state *state, static void enable_bs_jitter_was(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); u32 clear = 0; u32 set = 0; - if (!IS_ALDERLAKE_P(i915)) + if (!display->platform.alderlake_p) return; if (!IS_DISPLAY_STEP(display, STEP_D0, STEP_FOREVER)) -- cgit v1.2.3-59-g8ed1b From dddc53806dd2a10e210d5ea08caec6d3f92440b2 Mon Sep 17 00:00:00 2001 From: Vinay Belgaumkar Date: Thu, 16 Jan 2025 10:46:59 -0800 Subject: drm/xe/ptl: Apply Wa_13011645652 Extend Wa_13011645652 to PTL. Signed-off-by: Vinay Belgaumkar Reviewed-by: Stuart Summers Signed-off-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20250116184659.384874-1-vinay.belgaumkar@intel.com --- drivers/gpu/drm/xe/xe_wa_oob.rules | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules index 40438c3d9b72..228436532282 100644 --- a/drivers/gpu/drm/xe/xe_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules @@ -28,6 +28,7 @@ 16022287689 GRAPHICS_VERSION(2001) GRAPHICS_VERSION(2004) 13011645652 GRAPHICS_VERSION(2004) + GRAPHICS_VERSION(3001) 14022293748 GRAPHICS_VERSION(2001) GRAPHICS_VERSION(2004) 22019794406 GRAPHICS_VERSION(2001) -- cgit v1.2.3-59-g8ed1b From 5947642004bfd56436ce63d3e65d517b5be52549 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 20 Jan 2025 09:51:17 +0530 Subject: drm/i915/display: Add support for SNPS PHY HDMI PLL algorithm for DG2 Add helpers to calculate the necessary parameters for configuring the HDMI PLL for SNPS MPLLB and C10 PHY. The pll parameters are computed for desired pixel clock, curve data and other inputs used for interpolation and finally stored in the pll_state. Currently the helper is used to compute PLLs for DG2 SNPS PHY. Support for computing Plls for C10 PHY is added in subsequent patches. v2: -Used kernel types instead of C99 types. (Jani) -Fixed styling issues and renamed few variables to more meaningful names. (Jani) -Added Xe make file changes. (Jani) -Fixed build errors reported by kernel test robot v3: -Renamed helper to align with file name. (Jani) v4: -Removed erroraneous comment, and added Bspec# as part of trailer. (Suraj) -Fixed warning flagged by kernel test robot. Bspec: 54032 Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Tested-by: Khaled Almahallawy Link: https://patchwork.freedesktop.org/patch/msgid/20250120042122.1029481-2-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c | 288 +++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h | 15 ++ drivers/gpu/drm/xe/Makefile | 1 + 4 files changed, 305 insertions(+) create mode 100644 drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c create mode 100644 drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 3dda9f0eda82..4caa8e30bc98 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -346,6 +346,7 @@ i915-y += \ display/intel_pps.o \ display/intel_qp_tables.o \ display/intel_sdvo.o \ + display/intel_snps_hdmi_pll.o \ display/intel_snps_phy.o \ display/intel_tv.o \ display/intel_vdsc.o \ diff --git a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c new file mode 100644 index 000000000000..0e52578ef181 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2025 Synopsys, Inc., Intel Corporation + */ + +#include + +#include "intel_display_types.h" +#include "intel_snps_phy.h" +#include "intel_snps_phy_regs.h" +#include "intel_snps_hdmi_pll.h" + +#define INTEL_SNPS_PHY_HDMI_4999MHZ 4999999900ULL +#define INTEL_SNPS_PHY_HDMI_16GHZ 16000000000ULL +#define INTEL_SNPS_PHY_HDMI_9999MHZ (2 * INTEL_SNPS_PHY_HDMI_4999MHZ) + +#define CURVE0_MULTIPLIER 1000000000 +#define CURVE1_MULTIPLIER 100 +#define CURVE2_MULTIPLIER 1000000000000ULL + +struct pll_output_params { + u32 ssc_up_spread; + u32 mpll_div5_en; + u32 hdmi_div; + u32 ana_cp_int; + u32 ana_cp_prop; + u32 refclk_postscalar; + u32 tx_clk_div; + u32 fracn_quot; + u32 fracn_rem; + u32 fracn_den; + u32 fracn_en; + u32 pmix_en; + u32 multiplier; + int mpll_ana_v2i; + int ana_freq_vco; +}; + +static s64 interp(s64 x, s64 x1, s64 x2, s64 y1, s64 y2) +{ + s64 dydx; + + dydx = DIV_ROUND_UP_ULL((y2 - y1) * 100000, (x2 - x1)); + + return (y1 + DIV_ROUND_UP_ULL(dydx * (x - x1), 100000)); +} + +static void get_ana_cp_int_prop(u32 vco_clk, + u32 refclk_postscalar, + int mpll_ana_v2i, + int c, int a, + const u64 curve_freq_hz[2][8], + const u64 curve_0[2][8], + const u64 curve_1[2][8], + const u64 curve_2[2][8], + u32 *ana_cp_int, + u32 *ana_cp_prop) +{ + u64 vco_div_refclk_float; + u64 curve_0_interpolated; + u64 curve_2_interpolated; + u64 curve_1_interpolated; + u64 curve_2_scaled1; + u64 curve_2_scaled2; + u64 adjusted_vco_clk1; + u64 adjusted_vco_clk2; + u64 curve_2_scaled_int; + u64 interpolated_product; + u64 scaled_interpolated_sqrt; + u64 scaled_vco_div_refclk1; + u64 scaled_vco_div_refclk2; + u64 ana_cp_int_temp; + u64 temp; + + vco_div_refclk_float = vco_clk * DIV_ROUND_DOWN_ULL(1000000000000ULL, refclk_postscalar); + + /* Interpolate curve values at the target vco_clk frequency */ + curve_0_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1], + curve_0[c][a], curve_0[c][a + 1]); + + curve_2_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1], + curve_2[c][a], curve_2[c][a + 1]); + + curve_1_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1], + curve_1[c][a], curve_1[c][a + 1]); + + curve_1_interpolated = DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE1_MULTIPLIER); + + /* + * Scale curve_2_interpolated based on mpll_ana_v2i, for integer part + * ana_cp_int and for the proportional part ana_cp_prop + */ + temp = curve_2_interpolated * (4 - mpll_ana_v2i); + curve_2_scaled1 = DIV_ROUND_DOWN_ULL(temp, 16000); + curve_2_scaled2 = DIV_ROUND_DOWN_ULL(temp, 160); + + /* Scale vco_div_refclk for ana_cp_int */ + scaled_vco_div_refclk1 = 112008301 * DIV_ROUND_DOWN_ULL(vco_div_refclk_float, 100000); + + adjusted_vco_clk1 = CURVE2_MULTIPLIER * + DIV_ROUND_DOWN_ULL(scaled_vco_div_refclk1, (curve_0_interpolated * + DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE0_MULTIPLIER))); + + ana_cp_int_temp = + DIV_ROUND_CLOSEST_ULL(DIV_ROUND_DOWN_ULL(adjusted_vco_clk1, curve_2_scaled1), + CURVE2_MULTIPLIER); + + *ana_cp_int = max(1, min(ana_cp_int_temp, 127)); + + curve_2_scaled_int = curve_2_scaled1 * (*ana_cp_int); + + interpolated_product = curve_1_interpolated * + (curve_2_scaled_int * DIV_ROUND_DOWN_ULL(curve_0_interpolated, + CURVE0_MULTIPLIER)); + + scaled_interpolated_sqrt = + int_sqrt(DIV_ROUND_UP_ULL(interpolated_product, vco_div_refclk_float) * + DIV_ROUND_DOWN_ULL(1000000000000ULL, 55)); + + /* Scale vco_div_refclk for ana_cp_int */ + scaled_vco_div_refclk2 = DIV_ROUND_UP_ULL(vco_div_refclk_float, 1000000); + adjusted_vco_clk2 = 1460281 * DIV_ROUND_UP_ULL(scaled_interpolated_sqrt * + scaled_vco_div_refclk2, + curve_1_interpolated); + + *ana_cp_prop = DIV_ROUND_UP_ULL(adjusted_vco_clk2, curve_2_scaled2); + *ana_cp_prop = max(1, min(*ana_cp_prop, 127)); +} + +static void compute_hdmi_tmds_pll(u64 pixel_clock, u32 refclk, + u32 ref_range, + u32 ana_cp_int_gs, + u32 ana_cp_prop_gs, + const u64 curve_freq_hz[2][8], + const u64 curve_0[2][8], + const u64 curve_1[2][8], + const u64 curve_2[2][8], + u32 prescaler_divider, + struct pll_output_params *pll_params) +{ + u64 datarate = pixel_clock * 10000; + u32 ssc_up_spread = 1; + u32 mpll_div5_en = 1; + u32 hdmi_div = 1; + u32 ana_cp_int; + u32 ana_cp_prop; + u32 refclk_postscalar = refclk >> prescaler_divider; + u32 tx_clk_div; + u64 vco_clk; + u64 vco_clk_do_div; + u32 vco_div_refclk_integer; + u32 vco_div_refclk_fracn; + u32 fracn_quot; + u32 fracn_rem; + u32 fracn_den; + u32 fracn_en; + u32 pmix_en; + u32 multiplier; + int mpll_ana_v2i; + int ana_freq_vco = 0; + int c, a = 0; + int i; + + /* Select appropriate v2i point */ + if (datarate <= INTEL_SNPS_PHY_HDMI_9999MHZ) { + mpll_ana_v2i = 2; + tx_clk_div = ilog2(DIV_ROUND_DOWN_ULL(INTEL_SNPS_PHY_HDMI_9999MHZ, datarate)); + } else { + mpll_ana_v2i = 3; + tx_clk_div = ilog2(DIV_ROUND_DOWN_ULL(INTEL_SNPS_PHY_HDMI_16GHZ, datarate)); + } + vco_clk = (datarate << tx_clk_div) >> 1; + + vco_div_refclk_integer = DIV_ROUND_DOWN_ULL(vco_clk, refclk_postscalar); + vco_clk_do_div = do_div(vco_clk, refclk_postscalar); + vco_div_refclk_fracn = DIV_ROUND_DOWN_ULL(vco_clk_do_div << 32, refclk_postscalar); + + fracn_quot = vco_div_refclk_fracn >> 16; + fracn_rem = vco_div_refclk_fracn & 0xffff; + fracn_rem = fracn_rem - (fracn_rem >> 15); + fracn_den = 0xffff; + fracn_en = (fracn_quot != 0 || fracn_rem != 0) ? 1 : 0; + pmix_en = fracn_en; + multiplier = (vco_div_refclk_integer - 16) * 2; + /* Curve selection for ana_cp_* calculations. One curve hardcoded per v2i range */ + c = mpll_ana_v2i - 2; + + /* Find the right segment of the table */ + for (i = 0; i < 8; i += 2) { + if (vco_clk <= curve_freq_hz[c][i + 1]) { + a = i; + ana_freq_vco = 3 - (a >> 1); + break; + } + } + + get_ana_cp_int_prop(vco_clk, refclk_postscalar, mpll_ana_v2i, c, a, + curve_freq_hz, curve_0, curve_1, curve_2, + &ana_cp_int, &ana_cp_prop); + + pll_params->ssc_up_spread = ssc_up_spread; + pll_params->mpll_div5_en = mpll_div5_en; + pll_params->hdmi_div = hdmi_div; + pll_params->ana_cp_int = ana_cp_int; + pll_params->refclk_postscalar = refclk_postscalar; + pll_params->tx_clk_div = tx_clk_div; + pll_params->fracn_quot = fracn_quot; + pll_params->fracn_rem = fracn_rem; + pll_params->fracn_den = fracn_den; + pll_params->fracn_en = fracn_en; + pll_params->pmix_en = pmix_en; + pll_params->multiplier = multiplier; + pll_params->ana_cp_prop = ana_cp_prop; + pll_params->mpll_ana_v2i = mpll_ana_v2i; + pll_params->ana_freq_vco = ana_freq_vco; +} + +void intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state *pll_state, u64 pixel_clock) +{ + /* x axis frequencies. One curve in each array per v2i point */ + static const u64 dg2_curve_freq_hz[2][8] = { + { 2500000000ULL, 3000000000ULL, 3000000000ULL, 3500000000ULL, 3500000000ULL, + 4000000000ULL, 4000000000ULL, 5000000000ULL }, + { 4000000000ULL, 4600000000ULL, 4601000000ULL, 5400000000ULL, 5401000000ULL, + 6600000000ULL, 6601000000ULL, 8001000000ULL } + }; + + /* y axis heights multiplied with 1000000000 */ + static const u64 dg2_curve_0[2][8] = { + { 34149871, 39803269, 36034544, 40601014, 35646940, 40016109, 35127987, 41889522 }, + { 70000000, 78770454, 70451838, 80427119, 70991400, 84230173, 72945921, 87064218 } + }; + + /* Multiplied with 100 */ + static const u64 dg2_curve_1[2][8] = { + { 85177000000000ULL, 79385227160000ULL, 95672603580000ULL, 88857207160000ULL, + 109379790900000ULL, 103528193900000ULL, 131941242400000ULL, 117279000000000ULL }, + { 60255000000000ULL, 55569000000000ULL, 72036000000000ULL, 69509000000000ULL, + 81785000000000ULL, 731030000000000ULL, 96591000000000ULL, 69077000000000ULL } + }; + + /* Multiplied with 1000000000000 */ + static const u64 dg2_curve_2[2][8] = { + { 2186930000ULL, 2835287134ULL, 2395395343ULL, 2932270687ULL, 2351887545ULL, + 2861031697ULL, 2294149152ULL, 3091730000ULL }, + { 4560000000ULL, 5570000000ULL, 4610000000ULL, 5770000000ULL, 4670000000ULL, + 6240000000ULL, 4890000000ULL, 6600000000ULL } + }; + + struct pll_output_params pll_params; + u32 refclk = 100000000; + u32 prescaler_divider = 1; + u32 ref_range = 3; + u32 ana_cp_int_gs = 64; + u32 ana_cp_prop_gs = 124; + + compute_hdmi_tmds_pll(pixel_clock, refclk, ref_range, ana_cp_int_gs, ana_cp_prop_gs, + dg2_curve_freq_hz, dg2_curve_0, dg2_curve_1, dg2_curve_2, + prescaler_divider, &pll_params); + + pll_state->clock = pixel_clock; + pll_state->ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, ref_range); + pll_state->mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, pll_params.ana_cp_int) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, pll_params.ana_cp_prop) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, ana_cp_int_gs) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, ana_cp_prop_gs); + pll_state->mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, pll_params.mpll_div5_en) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, pll_params.tx_clk_div) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, pll_params.pmix_en) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, pll_params.mpll_ana_v2i) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, pll_params.ana_freq_vco); + pll_state->mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, prescaler_divider) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, pll_params.multiplier) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, pll_params.hdmi_div); + pll_state->mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, pll_params.fracn_en) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, pll_params.fracn_den); + pll_state->mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, pll_params.fracn_quot) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, pll_params.fracn_rem); + pll_state->mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, pll_params.ssc_up_spread); +} diff --git a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h new file mode 100644 index 000000000000..70b7023c1135 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2025 Synopsys, Inc., Intel Corporation + */ + +#ifndef __INTEL_SNPS_HDMI_PLL_H__ +#define __INTEL_SNPS_HDMI_PLL_H__ + +#include + +struct intel_mpllb_state; + +void intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state *pll_state, u64 pixel_clock); + +#endif /* __INTEL_SNPS_HDMI_PLL_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 81f63258a7e1..f639c9d75023 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -262,6 +262,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_psr.o \ i915-display/intel_qp_tables.o \ i915-display/intel_quirks.o \ + i915-display/intel_snps_hdmi_pll.o \ i915-display/intel_snps_phy.o \ i915-display/intel_tc.o \ i915-display/intel_vblank.o \ -- cgit v1.2.3-59-g8ed1b From 560de03d15c06a3c17b20733a5b200ac0f78ae40 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 20 Jan 2025 09:51:18 +0530 Subject: drm/i915/snps_phy: Use HDMI PLL algorithm for DG2 Try SNPS_PHY HDMI alogorithm, if there are no pre-computed tables. Also get rid of the helper to get rate for HDMI snps phy, as we no longer depend only on pre-computed tables. v2: -Prefer pre-computed tables over computed values from algorithm. (Jani) Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Tested-by: Khaled Almahallawy Link: https://patchwork.freedesktop.org/patch/msgid/20250120042122.1029481-3-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 -- drivers/gpu/drm/i915/display/intel_snps_phy.c | 37 +++++++-------------------- drivers/gpu/drm/i915/display/intel_snps_phy.h | 1 - 3 files changed, 9 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index ed29dd0ccef0..a0133713725b 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1918,8 +1918,6 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, */ if (DISPLAY_VER(display) >= 14) return intel_cx0_phy_check_hdmi_link_rate(hdmi, clock); - else if (IS_DG2(dev_priv)) - return intel_snps_phy_check_hdmi_link_rate(clock); return MODE_OK; } diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 41fe26dc200b..ec3c0ea2f4cb 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -11,6 +11,7 @@ #include "intel_ddi_buf_trans.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_snps_hdmi_pll.h" #include "intel_snps_phy.h" #include "intel_snps_phy_regs.h" @@ -1788,24 +1789,9 @@ intel_mpllb_tables_get(struct intel_crtc_state *crtc_state, int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); const struct intel_mpllb_state * const *tables; int i; - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { - if (intel_snps_phy_check_hdmi_link_rate(crtc_state->port_clock) - != MODE_OK) { - /* - * FIXME: Can only support fixed HDMI frequencies - * until we have a proper algorithm under a valid - * license. - */ - drm_dbg_kms(&i915->drm, "Can't support HDMI link rate %d\n", - crtc_state->port_clock); - return -EINVAL; - } - } - tables = intel_mpllb_tables_get(crtc_state, encoder); if (!tables) return -EINVAL; @@ -1817,6 +1803,14 @@ int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state, } } + /* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */ + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { + intel_snps_hdmi_pll_compute_mpllb(&crtc_state->dpll_hw_state.mpllb, + crtc_state->port_clock); + + return 0; + } + return -EINVAL; } @@ -1982,19 +1976,6 @@ void intel_mpllb_readout_hw_state(struct intel_encoder *encoder, pll_state->mpllb_div &= ~SNPS_PHY_MPLLB_FORCE_EN; } -int intel_snps_phy_check_hdmi_link_rate(int clock) -{ - const struct intel_mpllb_state * const *tables = dg2_hdmi_tables; - int i; - - for (i = 0; tables[i]; i++) { - if (clock == tables[i]->clock) - return MODE_OK; - } - - return MODE_CLOCK_RANGE; -} - void intel_mpllb_state_verify(struct intel_atomic_state *state, struct intel_crtc *crtc) { diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.h b/drivers/gpu/drm/i915/display/intel_snps_phy.h index bc08b92a7cd9..1dd564ed9fa8 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.h +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.h @@ -30,7 +30,6 @@ void intel_mpllb_readout_hw_state(struct intel_encoder *encoder, int intel_mpllb_calc_port_clock(struct intel_encoder *encoder, const struct intel_mpllb_state *pll_state); -int intel_snps_phy_check_hdmi_link_rate(int clock); void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_mpllb_state_verify(struct intel_atomic_state *state, -- cgit v1.2.3-59-g8ed1b From 18176f56942a596c5d03ed69ef30ad72f67a7edc Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Wed, 22 Jan 2025 21:58:50 +0530 Subject: drm/i915/cx0_phy_regs: Add C10 registers bits Add C10 register bits to be used for computing HDMI PLLs with algorithm. v2: Add bspec reference. (Suraj) v3: Use REG_BIT8 like other reg bits/masks. (Jani) Bspec: 74166 Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Tested-by: Khaled Almahallawy Link: https://patchwork.freedesktop.org/patch/msgid/20250122162850.1861410-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h index a47fd1aef9f0..5794ece42e92 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h @@ -214,10 +214,34 @@ /* C10 Vendor Registers */ #define PHY_C10_VDR_PLL(idx) (0xC00 + (idx)) +#define C10_PLL0_SSC_EN REG_BIT8(0) +#define C10_PLL0_DIVCLK_EN REG_BIT8(1) +#define C10_PLL0_DIV5CLK_EN REG_BIT8(2) +#define C10_PLL0_WORDDIV2_EN REG_BIT8(3) #define C10_PLL0_FRACEN REG_BIT8(4) +#define C10_PLL0_PMIX_EN REG_BIT8(5) +#define C10_PLL0_ANA_FREQ_VCO_MASK REG_GENMASK8(7, 6) +#define C10_PLL1_DIV_MULTIPLIER_MASK REG_GENMASK8(7, 0) +#define C10_PLL2_MULTIPLIERL_MASK REG_GENMASK8(7, 0) #define C10_PLL3_MULTIPLIERH_MASK REG_GENMASK8(3, 0) +#define C10_PLL8_SSC_UP_SPREAD REG_BIT8(5) +#define C10_PLL9_FRACN_DENL_MASK REG_GENMASK8(7, 0) +#define C10_PLL10_FRACN_DENH_MASK REG_GENMASK8(7, 0) +#define C10_PLL11_FRACN_QUOT_L_MASK REG_GENMASK8(7, 0) +#define C10_PLL12_FRACN_QUOT_H_MASK REG_GENMASK8(7, 0) +#define C10_PLL13_FRACN_REM_L_MASK REG_GENMASK8(7, 0) +#define C10_PLL14_FRACN_REM_H_MASK REG_GENMASK8(7, 0) #define C10_PLL15_TXCLKDIV_MASK REG_GENMASK8(2, 0) #define C10_PLL15_HDMIDIV_MASK REG_GENMASK8(5, 3) +#define C10_PLL15_PIXELCLKDIV_MASK REG_GENMASK8(7, 6) +#define C10_PLL16_ANA_CPINT REG_GENMASK8(6, 0) +#define C10_PLL16_ANA_CPINTGS_L REG_BIT8(7) +#define C10_PLL17_ANA_CPINTGS_H_MASK REG_GENMASK8(5, 0) +#define C10_PLL17_ANA_CPPROP_L_MASK REG_GENMASK8(7, 6) +#define C10_PLL18_ANA_CPPROP_H_MASK REG_GENMASK8(4, 0) +#define C10_PLL18_ANA_CPPROPGS_L_MASK REG_GENMASK8(7, 5) +#define C10_PLL19_ANA_CPPROPGS_H_MASK REG_GENMASK8(3, 0) +#define C10_PLL19_ANA_V2I_MASK REG_GENMASK8(5, 4) #define PHY_C10_VDR_CMN(idx) (0xC20 + (idx)) #define C10_CMN0_REF_RANGE REG_FIELD_PREP(REG_GENMASK(4, 0), 1) -- cgit v1.2.3-59-g8ed1b From 82ecaae2360776dcd0b9abf9ae6b947c28025931 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 20 Jan 2025 09:51:20 +0530 Subject: drm/i915/intel_snps_hdmi_pll: Compute C10 HDMI PLLs with algorithm Add support for computing C10 HDMI PLLS using the HDMI PLL algorithm. v2: Fix styling issues. (Jani) v3: Rename function to align with filename. (Jani) v4: Add Bspec reference. (Suraj) Bspec: 74166 Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Tested-by: Khaled Almahallawy Link: https://patchwork.freedesktop.org/patch/msgid/20250120042122.1029481-5-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c | 76 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h | 2 + 2 files changed, 78 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c index 0e52578ef181..c6321dafef4f 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c +++ b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c @@ -5,6 +5,7 @@ #include +#include "intel_cx0_phy_regs.h" #include "intel_display_types.h" #include "intel_snps_phy.h" #include "intel_snps_phy_regs.h" @@ -286,3 +287,78 @@ void intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state *pll_state, u64 pll_state->mpllb_sscen = REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, pll_params.ssc_up_spread); } + +void intel_snps_hdmi_pll_compute_c10pll(struct intel_c10pll_state *pll_state, u64 pixel_clock) +{ + /* x axis frequencies. One curve in each array per v2i point */ + static const u64 c10_curve_freq_hz[2][8] = { + { 2500000000ULL, 3000000000ULL, 3000000000ULL, 3500000000ULL, 3500000000ULL, + 4000000000ULL, 4000000000ULL, 5000000000ULL }, + { 4000000000ULL, 4600000000ULL, 4601000000ULL, 5400000000ULL, 5401000000ULL, + 6600000000ULL, 6601000000ULL, 8001000000ULL } + }; + + /* y axis heights multiplied with 1000000000 */ + static const u64 c10_curve_0[2][8] = { + { 41174500, 48605500, 42973700, 49433100, 42408600, 47681900, 40297400, 49131400 }, + { 82056800, 94420700, 82323400, 96370600, 81273300, 98630100, 81728700, 99105700} + }; + + static const u64 c10_curve_1[2][8] = { + { 73300000000000ULL, 66000000000000ULL, 83100000000000ULL, 75300000000000ULL, + 99700000000000ULL, 92300000000000ULL, 125000000000000ULL, 110000000000000ULL }, + { 53700000000000ULL, 47700000000000ULL, 62200000000000ULL, 54400000000000ULL, + 75100000000000ULL, 63400000000000ULL, 90600000000000ULL, 76300000000000ULL } + }; + + /* Multiplied with 1000000000000 */ + static const u64 c10_curve_2[2][8] = { + { 2415790000ULL, 3136460000ULL, 2581990000ULL, 3222670000ULL, 2529330000ULL, + 3042020000ULL, 2336970000ULL, 3191460000ULL}, + { 4808390000ULL, 5994250000ULL, 4832730000ULL, 6193730000ULL, 4737700000ULL, + 6428750000ULL, 4779200000ULL, 6479340000ULL } + }; + + struct pll_output_params pll_params; + u32 refclk = 38400000; + u32 prescaler_divider = 0; + u32 ref_range = 1; + u32 ana_cp_int_gs = 30; + u32 ana_cp_prop_gs = 28; + + compute_hdmi_tmds_pll(pixel_clock, refclk, ref_range, + ana_cp_int_gs, ana_cp_prop_gs, + c10_curve_freq_hz, c10_curve_0, + c10_curve_1, c10_curve_2, prescaler_divider, + &pll_params); + + pll_state->tx = 0x10; + pll_state->cmn = 0x1; + pll_state->pll[0] = REG_FIELD_PREP(C10_PLL0_DIV5CLK_EN, pll_params.mpll_div5_en) | + REG_FIELD_PREP(C10_PLL0_FRACEN, pll_params.fracn_en) | + REG_FIELD_PREP(C10_PLL0_PMIX_EN, pll_params.pmix_en) | + REG_FIELD_PREP(C10_PLL0_ANA_FREQ_VCO_MASK, pll_params.ana_freq_vco); + pll_state->pll[2] = REG_FIELD_PREP(C10_PLL2_MULTIPLIERL_MASK, pll_params.multiplier); + pll_state->pll[3] = REG_FIELD_PREP(C10_PLL3_MULTIPLIERH_MASK, pll_params.multiplier >> 8); + pll_state->pll[8] = REG_FIELD_PREP(C10_PLL8_SSC_UP_SPREAD, pll_params.ssc_up_spread); + pll_state->pll[9] = REG_FIELD_PREP(C10_PLL9_FRACN_DENL_MASK, pll_params.fracn_den); + pll_state->pll[10] = REG_FIELD_PREP(C10_PLL10_FRACN_DENH_MASK, pll_params.fracn_den >> 8); + pll_state->pll[11] = REG_FIELD_PREP(C10_PLL11_FRACN_QUOT_L_MASK, pll_params.fracn_quot); + pll_state->pll[12] = REG_FIELD_PREP(C10_PLL12_FRACN_QUOT_H_MASK, + pll_params.fracn_quot >> 8); + + pll_state->pll[13] = REG_FIELD_PREP(C10_PLL13_FRACN_REM_L_MASK, pll_params.fracn_rem); + pll_state->pll[14] = REG_FIELD_PREP(C10_PLL14_FRACN_REM_H_MASK, pll_params.fracn_rem >> 8); + pll_state->pll[15] = REG_FIELD_PREP(C10_PLL15_TXCLKDIV_MASK, pll_params.tx_clk_div) | + REG_FIELD_PREP(C10_PLL15_HDMIDIV_MASK, pll_params.hdmi_div); + pll_state->pll[16] = REG_FIELD_PREP(C10_PLL16_ANA_CPINT, pll_params.ana_cp_int) | + REG_FIELD_PREP(C10_PLL16_ANA_CPINTGS_L, ana_cp_int_gs); + pll_state->pll[17] = REG_FIELD_PREP(C10_PLL17_ANA_CPINTGS_H_MASK, ana_cp_int_gs >> 1) | + REG_FIELD_PREP(C10_PLL17_ANA_CPPROP_L_MASK, pll_params.ana_cp_prop); + pll_state->pll[18] = + REG_FIELD_PREP(C10_PLL18_ANA_CPPROP_H_MASK, pll_params.ana_cp_prop >> 2) | + REG_FIELD_PREP(C10_PLL18_ANA_CPPROPGS_L_MASK, ana_cp_prop_gs); + + pll_state->pll[19] = REG_FIELD_PREP(C10_PLL19_ANA_CPPROPGS_H_MASK, ana_cp_prop_gs >> 3) | + REG_FIELD_PREP(C10_PLL19_ANA_V2I_MASK, pll_params.mpll_ana_v2i); +} diff --git a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h index 70b7023c1135..aac70c4bb0f8 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h +++ b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h @@ -8,8 +8,10 @@ #include +struct intel_c10pll_state; struct intel_mpllb_state; void intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state *pll_state, u64 pixel_clock); +void intel_snps_hdmi_pll_compute_c10pll(struct intel_c10pll_state *pll_state, u64 pixel_clock); #endif /* __INTEL_SNPS_HDMI_PLL_H__ */ -- cgit v1.2.3-59-g8ed1b From 1efd5384277eb71fce20922579061cd3acdb07cf Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 20 Jan 2025 09:51:21 +0530 Subject: drm/i915/cx0_phy: Use HDMI PLL algorithm for C10 PHY Try HDMI PLL alogorithm for C10 PHY, if there are no pre-computed tables. Also get rid of the helpers to get rate for HDMI for C10/20 PHY, as we no longer depend only on pre-computed tables. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Tested-by: Khaled Almahallawy Link: https://patchwork.freedesktop.org/patch/msgid/20250120042122.1029481-6-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 49 +++++++--------------------- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 1 - drivers/gpu/drm/i915/display/intel_hdmi.c | 10 ------ 3 files changed, 11 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 857262fcbac9..39c98549ac4e 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -18,6 +18,7 @@ #include "intel_hdmi.h" #include "intel_panel.h" #include "intel_psr.h" +#include "intel_snps_hdmi_pll.h" #include "intel_tc.h" #define MB_WRITE_COMMITTED true @@ -2003,19 +2004,6 @@ static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = { NULL, }; -static int intel_c10_phy_check_hdmi_link_rate(int clock) -{ - const struct intel_c10pll_state * const *tables = mtl_c10_hdmi_tables; - int i; - - for (i = 0; tables[i]; i++) { - if (clock == tables[i]->clock) - return MODE_OK; - } - - return MODE_CLOCK_RANGE; -} - static const struct intel_c10pll_state * const * intel_c10pll_tables_get(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) @@ -2077,6 +2065,16 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, } } + /* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */ + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { + intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10, + crtc_state->port_clock); + intel_c10pll_update_pll(crtc_state, encoder); + crtc_state->dpll_hw_state.cx0pll.use_c10 = true; + + return 0; + } + return -EINVAL; } @@ -2281,31 +2279,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) return 0; } -static int intel_c20_phy_check_hdmi_link_rate(int clock) -{ - const struct intel_c20pll_state * const *tables = mtl_c20_hdmi_tables; - int i; - - for (i = 0; tables[i]; i++) { - if (clock == tables[i]->clock) - return MODE_OK; - } - - if (clock >= 25175 && clock <= 594000) - return MODE_OK; - - return MODE_CLOCK_RANGE; -} - -int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock) -{ - struct intel_digital_port *dig_port = hdmi_to_dig_port(hdmi); - - if (intel_encoder_is_c10phy(&dig_port->base)) - return intel_c10_phy_check_hdmi_link_rate(clock); - return intel_c20_phy_check_hdmi_link_rate(clock); -} - static const struct intel_c20pll_state * const * intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 711168882684..573fa7d3e88f 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -41,7 +41,6 @@ bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, const struct intel_cx0pll_state *b); void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); -int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock); int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); #endif /* __INTEL_CX0_PHY_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index a0133713725b..95584b61cf08 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1909,16 +1909,6 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, if (intel_encoder_is_tc(encoder) && clock > 500000 && clock < 532800) return MODE_CLOCK_RANGE; - /* - * SNPS PHYs' MPLLB table-based programming can only handle a fixed - * set of link rates. - * - * FIXME: We will hopefully get an algorithmic way of programming - * the MPLLB for HDMI in the future. - */ - if (DISPLAY_VER(display) >= 14) - return intel_cx0_phy_check_hdmi_link_rate(hdmi, clock); - return MODE_OK; } -- cgit v1.2.3-59-g8ed1b From c156ef573efe4230ef3dc1ff2ec0038fe0eb217f Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:10 +0530 Subject: drm/i915/gt: fix typos in i915/gt files. Fix all typos in files under drm/i915/gt reported by codespell tool. v2: Fix grammar mistake in comment. v3: Correct typo in commit log. Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-2-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/gen2_engine_cs.c | 2 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 8 ++++---- drivers/gpu/drm/i915/gt/intel_engine_types.h | 4 ++-- drivers/gpu/drm/i915/gt/intel_gt_irq.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt_mcr.c | 2 +- drivers/gpu/drm/i915/gt/intel_migrate.c | 4 ++-- drivers/gpu/drm/i915/gt/intel_mocs.c | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 2 +- drivers/gpu/drm/i915/gt/intel_rps_types.h | 4 ++-- drivers/gpu/drm/i915/gt/intel_sa_media.c | 2 +- drivers/gpu/drm/i915/gt/intel_sseu.c | 2 +- drivers/gpu/drm/i915/gt/intel_workarounds.c | 2 +- drivers/gpu/drm/i915/gt/selftest_execlists.c | 2 +- drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 2 +- drivers/gpu/drm/i915/gt/selftest_lrc.c | 2 +- drivers/gpu/drm/i915/gt/selftest_rc6.c | 2 +- drivers/gpu/drm/i915/gt/selftest_rps.c | 2 +- drivers/gpu/drm/i915/gt/shaders/README | 6 +++--- drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm | 2 +- drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm | 2 +- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 4 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 ++-- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 2 +- drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c | 2 +- 28 files changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/gen2_engine_cs.c b/drivers/gpu/drm/i915/gt/gen2_engine_cs.c index 4904d0f4162c..8116fd5987e2 100644 --- a/drivers/gpu/drm/i915/gt/gen2_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen2_engine_cs.c @@ -179,7 +179,7 @@ u32 *gen5_emit_breadcrumb(struct i915_request *rq, u32 *cs) return __gen2_emit_breadcrumb(rq, cs, 8, 8); } -/* Just userspace ABI convention to limit the wa batch bo to a resonable size */ +/* Just userspace ABI convention to limit the wa batch bo to a reasonable size */ #define I830_BATCH_LIMIT SZ_256K #define I830_TLB_ENTRIES (2) #define I830_WA_SIZE max(I830_TLB_ENTRIES * SZ_4K, I830_BATCH_LIMIT) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 4d30a86016f2..ec136eb12d48 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -308,7 +308,7 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class) /* * There is a discrepancy here between the size reported * by the register and the size of the context layout - * in the docs. Both are described as authorative! + * in the docs. Both are described as authoritative! * * The discrepancy is on the order of a few cachelines, * but the total is under one page (4k), which is our @@ -845,7 +845,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt) * Note that we have a catch-22 situation where we need to be able to access * the blitter forcewake domain to read the engine fuses, but at the same time * we need to know which engines are available on the system to know which - * forcewake domains are present. We solve this by intializing the forcewake + * forcewake domains are present. We solve this by initializing the forcewake * domains based on the full engine mask in the platform capabilities before * calling this function and pruning the domains for fused-off engines * afterwards. @@ -1411,7 +1411,7 @@ create_ggtt_bind_context(struct intel_engine_cs *engine) /* * MI_UPDATE_GTT can insert up to 511 PTE entries and there could be multiple - * bind requets at a time so get a bigger ring. + * bind requests at a time so get a bigger ring. */ return intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_512K, I915_GEM_HWS_GGTT_BIND_ADDR, @@ -1533,7 +1533,7 @@ int intel_engines_init(struct intel_gt *gt) /** * intel_engine_cleanup_common - cleans up the engine state created by - * the common initiailizers. + * the common initializers. * @engine: Engine to cleanup. * * This cleans up everything created by the common helpers. diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index fe1f85e5dda3..155b6255a63e 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -237,7 +237,7 @@ struct intel_engine_execlists { */ struct i915_request * const *active; /** - * @inflight: the set of contexts submitted and acknowleged by HW + * @inflight: the set of contexts submitted and acknowledged by HW * * The set of inflight contexts is managed by reading CS events * from the HW. On a context-switch event (not preemption), we @@ -260,7 +260,7 @@ struct intel_engine_execlists { unsigned int port_mask; /** - * @virtual: Queue of requets on a virtual engine, sorted by priority. + * @virtual: Queue of requests on a virtual engine, sorted by priority. * Each RB entry is a struct i915_priolist containing a list of requests * of the same priority. */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index 1240d44eeb85..75e802e10be2 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -480,7 +480,7 @@ void gen8_gt_irq_postinstall(struct intel_gt *gt) gen2_irq_init(uncore, GEN8_GT_IRQ_REGS(1), ~gt_interrupts[1], gt_interrupts[1]); /* * RPS interrupts will get enabled/disabled on demand when RPS itself - * is enabled/disabled. Same wil be the case for GuC interrupts. + * is enabled/disabled. Same will be the case for GuC interrupts. */ gen2_irq_init(uncore, GEN8_GT_IRQ_REGS(2), gt->pm_imr, gt->pm_ier); gen2_irq_init(uncore, GEN8_GT_IRQ_REGS(3), ~gt_interrupts[3], gt_interrupts[3]); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c index b8912bd6c08e..aab20d6466f5 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c @@ -239,7 +239,7 @@ static u32 rw_with_mcr_steering_fw(struct intel_gt *gt, * to remain in multicast mode for reads. There's no real * downside to this, so we'll just go ahead and do so on all * platforms; we'll only clear the multicast bit from the mask - * when exlicitly doing a write operation. + * when explicitly doing a write operation. */ if (rw_flag == FW_REG_WRITE) mcr_mask |= GEN11_MCR_MULTICAST; diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c index 6f7af4077135..aff5aca591e6 100644 --- a/drivers/gpu/drm/i915/gt/intel_migrate.c +++ b/drivers/gpu/drm/i915/gt/intel_migrate.c @@ -304,7 +304,7 @@ struct intel_context *intel_migrate_create_context(struct intel_migrate *m) struct intel_context *ce; /* - * We randomly distribute contexts across the engines upon constrction, + * We randomly distribute contexts across the engines upon construction, * as they all share the same pinned vm, and so in order to allow * multiple blits to run in parallel, we must construct each blit * to use a different range of the vm for its GTT. This has to be @@ -646,7 +646,7 @@ calculate_chunk_sz(struct drm_i915_private *i915, bool src_is_lmem, * When CHUNK_SZ is passed all the pages upto CHUNK_SZ * will be taken for the blt. in Flat-ccs supported * platform Smem obj will have more pages than required - * for main meory hence limit it to the required size + * for main memory hence limit it to the required size * for main memory */ return min_t(u64, bytes_to_cpy, CHUNK_SZ); diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index d791d63d49b4..cf41d325712e 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -675,7 +675,7 @@ void intel_mocs_init(struct intel_gt *gt) __init_mocs_table(gt->uncore, &table, global_mocs_offset()); /* - * Initialize the L3CC table as part of mocs initalization to make + * Initialize the L3CC table as part of mocs initialization to make * sure the LNCFCMOCSx registers are programmed for the subsequent * memory transactions including guc transactions */ diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index c2fe3fc78e76..33b55c581552 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1098,7 +1098,7 @@ static bool __intel_gt_unset_wedged(struct intel_gt *gt) dma_fence_default_wait(fence, false, MAX_SCHEDULE_TIMEOUT); dma_fence_put(fence); - /* Restart iteration after droping lock */ + /* Restart iteration after dropping lock */ spin_lock(&timelines->lock); tl = list_entry(&timelines->active_list, typeof(*tl), link); } diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 32f3b52a183a..f0b75986afb9 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -236,7 +236,7 @@ static int xcs_resume(struct intel_engine_cs *engine) /* * In case of resets fails because engine resumes from * incorrect RING_HEAD and then GPU may be then fed - * to invalid instrcutions, which may lead to unrecoverable + * to invalid instructions, which may lead to unrecoverable * hang. So at first write doesn't succeed then try again. */ ENGINE_WRITE_FW(engine, RING_HEAD, ring->head); diff --git a/drivers/gpu/drm/i915/gt/intel_rps_types.h b/drivers/gpu/drm/i915/gt/intel_rps_types.h index 6507fa3f6d1e..5135b90a2a40 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps_types.h +++ b/drivers/gpu/drm/i915/gt/intel_rps_types.h @@ -40,7 +40,7 @@ enum { /** * struct intel_rps_freq_caps - rps freq capabilities * @rp0_freq: non-overclocked max frequency - * @rp1_freq: "less than" RP0 power/freqency + * @rp1_freq: "less than" RP0 power/frequency * @min_freq: aka RPn, minimum frequency * * Freq caps exposed by HW, values are in "hw units" and intel_gpu_freq() @@ -90,7 +90,7 @@ struct intel_rps { u8 boost_freq; /* Frequency to request when wait boosting */ u8 idle_freq; /* Frequency to request when we are idle */ u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */ - u8 rp1_freq; /* "less than" RP0 power/freqency */ + u8 rp1_freq; /* "less than" RP0 power/frequency */ u8 rp0_freq; /* Non-overclocked max frequency. */ u16 gpll_ref_freq; /* vlv/chv GPLL reference frequency */ diff --git a/drivers/gpu/drm/i915/gt/intel_sa_media.c b/drivers/gpu/drm/i915/gt/intel_sa_media.c index 8c1dbcbcbc4f..2945526d52d1 100644 --- a/drivers/gpu/drm/i915/gt/intel_sa_media.c +++ b/drivers/gpu/drm/i915/gt/intel_sa_media.c @@ -27,7 +27,7 @@ int intel_sa_mediagt_setup(struct intel_gt *gt, phys_addr_t phys_addr, /* * Standalone media shares the general MMIO space with the primary - * GT. We'll re-use the primary GT's mapping. + * GT. We'll reuse the primary GT's mapping. */ uncore->regs = intel_uncore_regs(&i915->uncore); if (drm_WARN_ON(&i915->drm, uncore->regs == NULL)) diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c index c8fadf58d836..e4538dd726c8 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c @@ -687,7 +687,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt, * According to documentation software must consider the configuration * as 2x4x8 and hardware will translate this to 1x8x8. * - * Furthemore, even though SScount is three bits, maximum documented + * Furthermore, even though SScount is three bits, maximum documented * value for it is four. From this some rules/restrictions follow: * * 1. diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 570c91878189..3ea9b06de1be 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -1318,7 +1318,7 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal) * We'll do our default/implicit steering based on GSLICE (in the * sliceid field) and DSS (in the subsliceid field). If we can * find overlap between the valid MSLICE and/or LNCF values with - * a suitable GSLICE, then we can just re-use the default value and + * a suitable GSLICE, then we can just reuse the default value and * skip and explicit steering at runtime. * * We only need to look for overlap between GSLICE/MSLICE/LNCF to find diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c index 222ca7c44951..07bc0bbee20f 100644 --- a/drivers/gpu/drm/i915/gt/selftest_execlists.c +++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c @@ -53,7 +53,7 @@ static int wait_for_submit(struct intel_engine_cs *engine, if (i915_request_completed(rq)) /* that was quick! */ return 0; - /* Wait until the HW has acknowleged the submission (or err) */ + /* Wait until the HW has acknowledged the submission (or err) */ intel_engine_flush_submission(engine); if (!READ_ONCE(engine->execlists.pending[0]) && is_active(rq)) return 0; diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index 9ce8ff1c04fe..d99061735c58 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -548,7 +548,7 @@ static int igt_reset_fail_engine(void *arg) struct intel_engine_cs *engine; enum intel_engine_id id; - /* Check that we can recover from engine-reset failues */ + /* Check that we can recover from engine-reset failures */ if (!intel_has_reset_engine(gt)) return 0; diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index e17b8777d21d..22e750108c5f 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -63,7 +63,7 @@ static int wait_for_submit(struct intel_engine_cs *engine, if (i915_request_completed(rq)) /* that was quick! */ return 0; - /* Wait until the HW has acknowleged the submission (or err) */ + /* Wait until the HW has acknowledged the submission (or err) */ intel_engine_flush_submission(engine); if (!READ_ONCE(engine->execlists.pending[0]) && is_active(rq)) return 0; diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c index 1aa1446c8fb0..b272a7d44599 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rc6.c +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c @@ -211,7 +211,7 @@ int live_rc6_ctx_wa(void *arg) i915_reset_engine_count(error, engine); const u32 *res; - /* Use a sacrifical context */ + /* Use a sacrificial context */ ce = intel_context_create(engine); if (IS_ERR(ce)) { err = PTR_ERR(ce); diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index c207a4fb03bf..78c03e6c0861 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -22,7 +22,7 @@ #include "selftests/igt_spinner.h" #include "selftests/librapl.h" -/* Try to isolate the impact of cstates from determing frequency response */ +/* Try to isolate the impact of cstates from determining frequency response */ #define CPU_LATENCY 0 /* -1 to disable pm_qos, 0 to disable cstates */ static void dummy_rps_work(struct work_struct *wrk) diff --git a/drivers/gpu/drm/i915/gt/shaders/README b/drivers/gpu/drm/i915/gt/shaders/README index e7e96d7073c7..22f8dabed434 100644 --- a/drivers/gpu/drm/i915/gt/shaders/README +++ b/drivers/gpu/drm/i915/gt/shaders/README @@ -10,7 +10,7 @@ i915/gt/shaders/clear_kernel directory. The generated .c files should never be modified directly. Instead, any modification needs to be done on the on their respective ASM files and build instructions below -needes to be followed. +needs to be followed. Building ======== @@ -24,7 +24,7 @@ on building. Please make sure your Mesa tool is compiled with "-Dtools=intel" and "-Ddri-drivers=i965", and run this script from IGT source root directory" -The instructions bellow assume: +The instructions below assume: * IGT gpu tools source code is located on your home directory (~) as ~/igt * Mesa source code is located on your home directory (~) as ~/mesa and built under the ~/mesa/build directory @@ -43,4 +43,4 @@ igt $ ./scripts/generate_clear_kernel.sh -g ivb \ ~/igt/lib/i915/shaders/clear_kernel/hsw.asm ~ $ cd ~/igt igt $ ./scripts/generate_clear_kernel.sh -g hsw \ - -m ~/mesa/build/src/intel/tools/i965_asm \ No newline at end of file + -m ~/mesa/build/src/intel/tools/i965_asm diff --git a/drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm b/drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm index 5fdf384bb621..6c0c89daf96c 100644 --- a/drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm +++ b/drivers/gpu/drm/i915/gt/shaders/clear_kernel/hsw.asm @@ -24,7 +24,7 @@ mov(1) f0.1<1>UW g1.2<0,1,0>UW { align1 1N }; * DW 1.4 - Rsvd (intended for context ID) * DW 1.5 - [31:16]:SliceCount, [15:0]:SubSlicePerSliceCount * DW 1.6 - Rsvd MBZ (intended for Enable Wait on Total Thread Count) - * DW 1.7 - Rsvd MBZ (inteded for Total Thread Count) + * DW 1.7 - Rsvd MBZ (intended for Total Thread Count) * * Binding Table * diff --git a/drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm b/drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm index 97c7ac9e3854..27c28e63d6cc 100644 --- a/drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm +++ b/drivers/gpu/drm/i915/gt/shaders/clear_kernel/ivb.asm @@ -24,7 +24,7 @@ mov(1) f0.1<1>UW g1.2<0,1,0>UW { align1 1N }; * DW 1.4 - Rsvd (intended for context ID) * DW 1.5 - [31:16]:SliceCount, [15:0]:SubSlicePerSliceCount * DW 1.6 - Rsvd MBZ (intended for Enable Wait on Total Thread Count) - * DW 1.7 - Rsvd MBZ (inteded for Total Thread Count) + * DW 1.7 - Rsvd MBZ (intended for Total Thread Count) * * Binding Table * diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 1fc0c17b1230..803c0379d97d 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -81,7 +81,7 @@ struct guc_debug_capture_list { * * intel_guc_capture module uses these structures to maintain static * tables (per unique platform) that consists of lists of registers - * (offsets, names, flags,...) that are used at the ADS regisration + * (offsets, names, flags,...) that are used at the ADS registration * time as well as during runtime processing and reporting of error- * capture states generated by GuC just prior to engine reset events. */ @@ -200,7 +200,7 @@ struct intel_guc_state_capture { * dynamically allocate new nodes when receiving the G2H notification * because the event handlers for all G2H event-processing is called * by the ct processing worker queue and when that queue is being - * processed, there is no absoluate guarantee that we are not in the + * processed, there is no absolute guarantee that we are not in the * midst of a GT reset operation (which doesn't allow allocations). */ struct list_head cachelist; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 5949ff0b0161..9df80c325fc1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -690,7 +690,7 @@ int intel_guc_suspend(struct intel_guc *guc) * H2G MMIO command completes. * * Don't abort on a failure code from the GuC. Keep going and do the - * clean up in santize() and re-initialisation on resume and hopefully + * clean up in sanitize() and re-initialisation on resume and hopefully * the error here won't be problematic. */ ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 57b903132776..053780f562c1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -295,7 +295,7 @@ struct intel_guc { */ struct work_struct dead_guc_worker; /** - * @last_dead_guc_jiffies: timestamp of previous 'dead guc' occurrance + * @last_dead_guc_jiffies: timestamp of previous 'dead guc' occurrence * used to prevent a fundamentally broken system from continuously * reloading the GuC. */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 4ce6e2332a63..eded00f0c7e1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -408,7 +408,7 @@ enum guc_capture_type { GUC_CAPTURE_LIST_TYPE_MAX, }; -/* Class indecies for capture_class and capture_instance arrays */ +/* Class indices for capture_class and capture_instance arrays */ enum { GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE = 0, GUC_CAPTURE_LIST_CLASS_VIDEO = 1, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 12f1ba7ca9c1..3b1333a24a89 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1223,7 +1223,7 @@ __extend_last_switch(struct intel_guc *guc, u64 *prev_start, u32 new_start) * determine validity of these values. Instead we read the values multiple times * until they are consistent. In test runs, 3 attempts results in consistent * values. The upper bound is set to 6 attempts and may need to be tuned as per - * any new occurences. + * any new occurrences. */ static void __get_engine_usage_record(struct intel_engine_cs *engine, u32 *last_in, u32 *id, u32 *total) @@ -2995,7 +2995,7 @@ static int __guc_context_pin(struct intel_context *ce, /* * GuC context gets pinned in guc_request_alloc. See that function for - * explaination of why. + * explanation of why. */ return lrc_pin(ce, engine, vaddr); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 5b8080ec5315..90ba1b0b4c9d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -512,7 +512,7 @@ static int __uc_init_hw(struct intel_uc *uc) ERR_PTR(ret), attempts); } - /* Did we succeded or run out of retries? */ + /* Did we succeed or run out of retries? */ if (ret) goto err_log_capture; diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c index 26fdc392fce6..83801c992488 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c @@ -64,7 +64,7 @@ static int intel_hang_guc(void *arg) old_beat = engine->props.heartbeat_interval_ms; ret = intel_engine_set_heartbeat(engine, BEAT_INTERVAL); if (ret) { - gt_err(gt, "Failed to boost heatbeat interval: %pe\n", ERR_PTR(ret)); + gt_err(gt, "Failed to boost heartbeat interval: %pe\n", ERR_PTR(ret)); goto err; } -- cgit v1.2.3-59-g8ed1b From 61d9f028936b895d955e6d704055f5d64e6a8e0c Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:11 +0530 Subject: drm/i915/gvt: fix typos in i915/gvt files Fix all typos in files under drm/i915/gvt reported by codespell tool. v2: Correct comment styling. Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-3-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 15 ++++++++------- drivers/gpu/drm/i915/gvt/dmabuf.c | 2 +- drivers/gpu/drm/i915/gvt/edid.c | 2 +- drivers/gpu/drm/i915/gvt/gtt.c | 2 +- drivers/gpu/drm/i915/gvt/gvt.h | 8 +++++--- drivers/gpu/drm/i915/gvt/handlers.c | 6 +++--- drivers/gpu/drm/i915/gvt/kvmgt.c | 2 +- drivers/gpu/drm/i915/gvt/mmio_context.c | 6 +++--- drivers/gpu/drm/i915/gvt/scheduler.c | 11 ++++++----- drivers/gpu/drm/i915/gvt/vgpu.c | 6 +++--- 10 files changed, 32 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 6439c8e91a8d..f25ee2953baf 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1906,7 +1906,7 @@ static int perform_bb_shadow(struct parser_exec_state *s) s->vgpu->gtt.ggtt_mm : s->workload->shadow_mm; unsigned long start_offset = 0; - /* get the start gm address of the batch buffer */ + /* Get the start gm address of the batch buffer */ gma = get_gma_bb_from_cmd(s, 1); if (gma == INTEL_GVT_INVALID_ADDR) return -EFAULT; @@ -1921,15 +1921,16 @@ static int perform_bb_shadow(struct parser_exec_state *s) bb->ppgtt = (s->buf_addr_type == GTT_BUFFER) ? false : true; - /* the start_offset stores the batch buffer's start gma's - * offset relative to page boundary. so for non-privileged batch + /* + * The start_offset stores the batch buffer's start gma's + * offset relative to page boundary. So for non-privileged batch * buffer, the shadowed gem object holds exactly the same page - * layout as original gem object. This is for the convience of + * layout as original gem object. This is for the convenience of * replacing the whole non-privilged batch buffer page to this - * shadowed one in PPGTT at the same gma address. (this replacing + * shadowed one in PPGTT at the same gma address. (This replacing * action is not implemented yet now, but may be necessary in * future). - * for prileged batch buffer, we just change start gma address to + * For prileged batch buffer, we just change start gma address to * that of shadowed page. */ if (bb->ppgtt) @@ -1976,7 +1977,7 @@ static int perform_bb_shadow(struct parser_exec_state *s) /* * ip_va saves the virtual address of the shadow batch buffer, while * ip_gma saves the graphics address of the original batch buffer. - * As the shadow batch buffer is just a copy from the originial one, + * As the shadow batch buffer is just a copy from the original one, * it should be right to use shadow batch buffer'va and original batch * buffer's gma in pair. After all, we don't want to pin the shadow * buffer here (too early). diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 9efc3ca0ce82..4f599af766b0 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -436,7 +436,7 @@ int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args) dmabuf_obj_get(dmabuf_obj); } ret = 0; - gvt_dbg_dpy("vgpu%d: re-use dmabuf_obj ref %d, id %d\n", + gvt_dbg_dpy("vgpu%d: reuse dmabuf_obj ref %d, id %d\n", vgpu->id, kref_read(&dmabuf_obj->kref), gfx_plane_info->dmabuf_id); mutex_unlock(&vgpu->dmabuf_lock); diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c index 0a357ca42db1..89147d33168c 100644 --- a/drivers/gpu/drm/i915/gvt/edid.c +++ b/drivers/gpu/drm/i915/gvt/edid.c @@ -298,7 +298,7 @@ static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, int byte_count = byte_left; u32 reg_data = 0; - /* Data can only be recevied if previous settings correct */ + /* Data can only be received if previous settings correct */ if (vgpu_vreg_t(vgpu, PCH_GMBUS1) & GMBUS_SLAVE_READ) { if (byte_left <= 0) { memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 464fb17e82ee..2fa7ca19ba5d 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1193,7 +1193,7 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu, gvt_vdbg_mm("shadow 64K gtt entry\n"); /* * The layout of 64K page is special, the page size is - * controlled by uper PDE. To be simple, we always split + * controlled by upper PDE. To be simple, we always split * 64K page to smaller 4K pages in shadow PT. */ return split_64KB_gtt_entry(vgpu, spt, index, &se); diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 8580c6d057e7..01d890999f25 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -452,8 +452,10 @@ void intel_vgpu_free_resource(struct intel_vgpu *vgpu); void intel_vgpu_write_fence(struct intel_vgpu *vgpu, u32 fence, u64 value); -/* Macros for easily accessing vGPU virtual/shadow register. - Explicitly seperate use for typed MMIO reg or real offset.*/ +/* + * Macros for easily accessing vGPU virtual/shadow register. + * Explicitly separate use for typed MMIO reg or real offset. + */ #define vgpu_vreg_t(vgpu, reg) \ (*(u32 *)(vgpu->mmio.vreg + i915_mmio_reg_offset(reg))) #define vgpu_vreg(vgpu, offset) \ @@ -696,7 +698,7 @@ static inline void intel_gvt_mmio_set_cmd_write_patch( * @offset: register offset * * Returns: - * True if GPU commmand write to an MMIO should be patched + * True if GPU command write to an MMIO should be patched. */ static inline bool intel_gvt_mmio_is_cmd_write_patch( struct intel_gvt *gvt, unsigned int offset) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index ee473b45d1e4..4efee6797873 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -689,11 +689,11 @@ static void vgpu_update_refresh_rate(struct intel_vgpu *vgpu) u32 new_rate = 0; u32 *old_rate = &(intel_vgpu_port(vgpu, vgpu->display.port_num)->vrefresh_k); - /* Calcuate pixel clock by (ls_clk * M / N) */ + /* Calculate pixel clock by (ls_clk * M / N) */ pixel_clk = div_u64(mul_u32_u32(link_m, dp_br), link_n); pixel_clk *= MSEC_PER_SEC; - /* Calcuate refresh rate by (pixel_clk / (h_total * v_total)) */ + /* Calculate refresh rate by (pixel_clk / (h_total * v_total)) */ new_rate = DIV64_U64_ROUND_CLOSEST(mul_u64_u32_shr(pixel_clk, MSEC_PER_SEC, 0), mul_u32_u32(htotal + 1, vtotal + 1)); if (*old_rate != new_rate) @@ -2001,7 +2001,7 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, * vGPU reset, it's set on D0->D3 on PCI config write, and cleared after * vGPU reset if in resuming. * In S0ix exit, the device power state also transite from D3 to D0 as - * S3 resume, but no vGPU reset (triggered by QEMU devic model). After + * S3 resume, but no vGPU reset (triggered by QEMU device model). After * S0ix exit, all engines continue to work. However the d3_entered * remains set which will break next vGPU reset logic (miss the expected * PPGTT invalidation). diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index b27ff77bfb50..69830a5c49d3 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -142,7 +142,7 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, int ret; /* - * We pin the pages one-by-one to avoid allocating a big arrary + * We pin the pages one-by-one to avoid allocating a big array * on stack to hold pfns. */ for (npage = 0; npage < total_pages; npage++) { diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 273db14fd5fc..2f7208843367 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c @@ -53,7 +53,7 @@ struct engine_mmio { u32 value; }; -/* Raw offset is appened to each line for convenience. */ +/* Raw offset is append to each line for convenience. */ static struct engine_mmio gen8_engine_mmio_list[] __cacheline_aligned = { {RCS0, RING_MODE_GEN7(RENDER_RING_BASE), 0xffff, false}, /* 0x229c */ {RCS0, GEN9_CTX_PREEMPT_REG, 0x0, false}, /* 0x2248 */ @@ -576,8 +576,8 @@ void intel_gvt_switch_mmio(struct intel_vgpu *pre, /** * We are using raw mmio access wrapper to improve the - * performace for batch mmio read/write, so we need - * handle forcewake mannually. + * performance for batch mmio read/write, so we need + * handle forcewake manually. */ intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL); switch_mmio(pre, next, engine); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 23f2cc397ec9..6e87c10bc454 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -77,7 +77,7 @@ static void update_shadow_pdps(struct intel_vgpu_workload *workload) } /* - * when populating shadow ctx from guest, we should not overrride oa related + * When populating shadow ctx from guest, we should not override oa related * registers, so that they will not be overlapped by guest oa configs. Thus * made it possible to capture oa data from host for both host and guests. */ @@ -528,9 +528,10 @@ static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) int ret; list_for_each_entry(bb, &workload->shadow_bb, list) { - /* For privilge batch buffer and not wa_ctx, the bb_start_cmd_va + /* + * For privilege batch buffer and not wa_ctx, the bb_start_cmd_va * is only updated into ring_scan_buffer, not real ring address - * allocated in later copy_workload_to_ring_buffer. pls be noted + * allocated in later copy_workload_to_ring_buffer. Please be noted * shadow_ring_buffer_va is now pointed to real ring buffer va * in copy_workload_to_ring_buffer. */ @@ -546,7 +547,7 @@ static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) * here, rather than switch to shadow bb's gma * address, we directly use original batch buffer's * gma address, and send original bb to hardware - * directly + * directly. */ if (!bb->ppgtt) { i915_gem_ww_ctx_init(&ww, false); @@ -1774,7 +1775,7 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, } /** - * intel_vgpu_queue_workload - Qeue a vGPU workload + * intel_vgpu_queue_workload - Queue a vGPU workload * @workload: the workload to queue in */ void intel_vgpu_queue_workload(struct intel_vgpu_workload *workload) diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 63c751ca4119..11260392234a 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -78,7 +78,7 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu) * vGPU type name is defined as GVTg_Vx_y which contains the physical GPU * generation type (e.g V4 as BDW server, V5 as SKL server). * - * Depening on the physical SKU resource, we might see vGPU types like + * Depending on the physical SKU resource, we might see vGPU types like * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create different types of * vGPU on same physical GPU depending on available resource. Each vGPU * type will have a different number of avail_instance to indicate how @@ -417,7 +417,7 @@ out_unlock: * the whole vGPU to default state as when it is created. This vGPU function * is required both for functionary and security concerns.The ultimate goal * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we - * assign a vGPU to a virtual machine we must isse such reset first. + * assign a vGPU to a virtual machine we must issue such reset first. * * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec. @@ -428,7 +428,7 @@ out_unlock: * * The parameter dev_level is to identify if we will do DMLR or GT reset. * The parameter engine_mask is to specific the engines that need to be - * resetted. If value ALL_ENGINES is given for engine_mask, it means + * reset. If value ALL_ENGINES is given for engine_mask, it means * the caller requests a full GT reset that we will reset all virtual * GPU engines. For FLR, engine_mask is ignored. */ -- cgit v1.2.3-59-g8ed1b From 54296aa4cfe71800a68342decc7176b7e1779713 Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:12 +0530 Subject: drm/i915/gem: fix typos in i915/gem files Fix all typos in files under drm/i915/gem reported by codespell tool. v2: Codespell won't catch it, but it should be "user defined" and not "use defined". Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-4-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 6 +++--- drivers/gpu/drm/i915/gem/i915_gem_context_types.h | 6 +++--- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 4 ++-- drivers/gpu/drm/i915/gem/i915_gem_region.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_shrinker.c | 4 ++-- drivers/gpu/drm/i915/gem/i915_gem_tiling.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c | 2 +- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c0543c35cd6a..ab1af978911b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -238,7 +238,7 @@ static int proto_context_set_persistence(struct drm_i915_private *i915, * * However, if we cannot reset an engine by itself, we cannot * cleanup a hanging persistent context without causing - * colateral damage, and we should not pretend we can by + * collateral damage, and we should not pretend we can by * exposing the interface. */ if (!intel_has_reset_engine(to_gt(i915))) @@ -1589,7 +1589,7 @@ static int __context_set_persistence(struct i915_gem_context *ctx, bool state) * * However, if we cannot reset an engine by itself, we cannot * cleanup a hanging persistent context without causing - * colateral damage, and we should not pretend we can by + * collateral damage, and we should not pretend we can by * exposing the interface. */ if (!intel_has_reset_engine(to_gt(ctx->i915))) @@ -2328,7 +2328,7 @@ finalize_create_context_locked(struct drm_i915_file_private *file_priv, /* * One for the xarray and one for the caller. We need to grab - * the reference *prior* to making the ctx visble to userspace + * the reference *prior* to making the ctx visible to userspace * in gem_context_register(), as at any point after that * userspace can try to race us with another thread destroying * the context under our feet. diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index b6d97da63d1f..67ac2586a0f3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -245,9 +245,9 @@ struct i915_gem_context { * Execbuf uses the I915_EXEC_RING_MASK as an index into this * array to select which HW context + engine to execute on. For * the default array, the user_ring_map[] is used to translate - * the legacy uABI onto the approprate index (e.g. both + * the legacy uABI onto the appropriate index (e.g. both * I915_EXEC_DEFAULT and I915_EXEC_RENDER select the same - * context, and I915_EXEC_BSD is weird). For a use defined + * context, and I915_EXEC_BSD is weird). For a user defined * array, execbuf uses I915_EXEC_RING_MASK as a plain index. * * User defined by I915_CONTEXT_PARAM_ENGINE (when the @@ -276,7 +276,7 @@ struct i915_gem_context { * @vm: unique address space (GTT) * * In full-ppgtt mode, each context has its own address space ensuring - * complete seperation of one client from all others. + * complete separation of one client from all others. * * In other modes, this is a NULL pointer with the expectation that * the caller uses the shared global GTT. diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 3770828f2eaf..ee55caca67a1 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -276,7 +276,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, * For objects created by userspace through GEM_CREATE with pat_index * set by set_pat extension, simply return 0 here without touching * the cache setting, because such objects should have an immutable - * cache setting by desgin and always managed by userspace. + * cache setting by design and always managed by userspace. */ if (i915_gem_object_has_cache_level(obj, cache_level)) return 0; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index f151640c1d13..c8107502190d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -303,7 +303,7 @@ struct i915_execbuffer { struct intel_gt_buffer_pool_node *batch_pool; /** pool node for batch buffer */ /** - * Indicate either the size of the hastable used to resolve + * Indicate either the size of the hashtable used to resolve * relocation handles, or if negative that we are using a direct * index into the execobj[]. */ @@ -2543,7 +2543,7 @@ static int eb_pin_timeline(struct i915_execbuffer *eb, struct intel_context *ce, /* * Error path, cannot use intel_context_timeline_lock as - * that is user interruptable and this clean up step + * that is user interruptible and this clean up step * must be done. */ mutex_lock(&ce->timeline->mutex); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c index b09b74a2448b..636768d0f57e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c @@ -82,7 +82,7 @@ __i915_gem_object_create_region(struct intel_memory_region *mem, /* * Anything smaller than the min_page_size can't be freely inserted into - * the GTT, due to alignemnt restrictions. For such special objects, + * the GTT, due to alignment restrictions. For such special objects, * make sure we force memcpy based suspend-resume. In the future we can * revisit this, either by allowing special mis-aligned objects in the * migration path, or by mapping all of LMEM upfront using cheap 1G diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index 9117e9422844..aec41f0f098f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -25,7 +25,7 @@ static bool swap_available(void) static bool can_release_pages(struct drm_i915_gem_object *obj) { - /* Consider only shrinkable ojects. */ + /* Consider only shrinkable objects. */ if (!i915_gem_object_is_shrinkable(obj)) return false; @@ -261,7 +261,7 @@ skip: * i915_gem_shrink_all - Shrink buffer object caches completely * @i915: i915 device * - * This is a simple wraper around i915_gem_shrink() to aggressively shrink all + * This is a simple wrapper around i915_gem_shrink() to aggressively shrink all * caches completely. It also first waits for and retires all outstanding * requests to also be able to release backing storage for active objects. * diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index d9eb84c1d2f1..5ac23ff3feff 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -39,7 +39,7 @@ * Since neither of this applies for new tiling layouts on modern platforms like * W, Ys and Yf tiling GEM only allows object tiling to be set to X or Y tiled. * Anything else can be handled in userspace entirely without the kernel's - * invovlement. + * involvement. */ /** diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 10d8673641f7..1f4814968868 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -994,7 +994,7 @@ void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj) * If we need to place an LMEM resource which doesn't need CPU * access then we should try not to victimize mappable objects * first, since we likely end up stealing more of the mappable - * portion. And likewise when we try to find space for a mappble + * portion. And likewise when we try to find space for a mappable * object, we know not to ever victimize objects that don't * occupy any mappable pages. */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c index 041dab543b78..2f6b33edb9c9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c @@ -603,7 +603,7 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict, * sequence, where at the end we can do the move for real. * * The special case here is when the dst_mem is TTM_PL_SYSTEM, - * which doens't require any kind of move, so it should be safe + * which doesn't require any kind of move, so it should be safe * to skip all the below and call ttm_bo_move_null() here, where * the caller in __i915_ttm_get_pages() will take care of the * rest, since we should have a valid ttm_tt. diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 84d41e6ccf05..bd08605a1611 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1781,7 +1781,7 @@ static int igt_tmpfs_fallback(void *arg) /* * Make sure that we don't burst into a ball of flames upon falling back - * to tmpfs, which we rely on if on the off-chance we encouter a failure + * to tmpfs, which we rely on if on the off-chance we encounter a failure * when setting up gemfs. */ diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 99a9ade73956..804f74084bd4 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -1342,7 +1342,7 @@ static int igt_mmap_migrate(void *arg) } /* - * Allocate in the mappable portion, should be no suprises here. + * Allocate in the mappable portion, should be no surprises here. */ err = __igt_mmap_migrate(mixed, ARRAY_SIZE(mixed), mr, 0); if (err) -- cgit v1.2.3-59-g8ed1b From 5fe543ce678aeaa6298eca9fe49ea1eaea024a6b Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:13 +0530 Subject: drm/i915/pxp: fix typos in i915/pxp files Fix all typos in files under drm/i915/pxp reported by codespell tool. Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-5-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h | 2 +- drivers/gpu/drm/i915/pxp/intel_pxp_types.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h index 329b4fcdc040..929c20e98300 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h @@ -41,7 +41,7 @@ struct pxp43_huc_auth_out { /* PXP-Input-Packet: Init PXP session */ struct pxp43_create_arb_in { struct pxp_cmd_header header; - /* header.stream_id fields for vesion 4.3 of Init PXP session: */ + /* header.stream_id fields for version 4.3 of Init PXP session: */ #define PXP43_INIT_SESSION_VALID BIT(0) #define PXP43_INIT_SESSION_APPTYPE BIT(1) #define PXP43_INIT_SESSION_APPID GENMASK(17, 2) diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h index 07864b584cf4..febdbcd8d61e 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h @@ -21,7 +21,7 @@ struct drm_i915_private; */ struct intel_pxp { /** - * @ctrl_gt: poiner to the tile that owns the controls for PXP subsystem assets that + * @ctrl_gt: pointer to the tile that owns the controls for PXP subsystem assets that * the VDBOX, the KCR engine (and GSC CS depending on the platform) */ struct intel_gt *ctrl_gt; -- cgit v1.2.3-59-g8ed1b From accc7f5bf230864eec84b249104cb8649c993a62 Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:14 +0530 Subject: drm/i915/selftests: fix typos in i915/selftests files Fix all typos in files under drm/i915/selftests reported by codespell tool. v2: Fix commenting style Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-6-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/selftests/i915_gem.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 21 +++++++++++++-------- drivers/gpu/drm/i915/selftests/i915_vma.c | 15 ++++++++++----- 3 files changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index 0727492576be..e817d233df61 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -80,7 +80,7 @@ static void simulate_hibernate(struct drm_i915_private *i915) wakeref = intel_runtime_pm_get(&i915->runtime_pm); /* - * As a final sting in the tail, invalidate stolen. Under a real S4, + * As a final string in the tail, invalidate stolen. Under a real S4, * stolen is lost and needs to be refilled on resume. However, under * CI we merely do S4-device testing (as full S4 is too unreliable * for automated testing across a cluster), so to simulate the effect diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 5c397a2df70e..5816d515203a 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -287,7 +287,8 @@ static int lowlevel_hole(struct i915_address_space *vm, GEM_BUG_ON(count * BIT_ULL(aligned_size) > vm->total); GEM_BUG_ON(hole_start + count * BIT_ULL(aligned_size) > hole_end); - /* Ignore allocation failures (i.e. don't report them as + /* + * Ignore allocation failures (i.e. don't report them as * a test failure) as we are purposefully allocating very * large objects without checking that we have sufficient * memory. We expect to hit -ENOMEM. @@ -446,7 +447,8 @@ static int fill_hole(struct i915_address_space *vm, list_add(&obj->st_link, &objects); - /* Align differing sized objects against the edges, and + /* + * Align differing sized objects against the edges, and * check we don't walk off into the void when binding * them into the GTT. */ @@ -831,7 +833,8 @@ static int drunk_hole(struct i915_address_space *vm, return -ENOMEM; GEM_BUG_ON(!order); - /* Ignore allocation failures (i.e. don't report them as + /* + * Ignore allocation failures (i.e. don't report them as * a test failure) as we are purposefully allocating very * large objects without checking that we have sufficient * memory. We expect to hit -ENOMEM. @@ -964,7 +967,7 @@ static int __shrink_hole(struct i915_address_space *vm, break; if (igt_timeout(end_time, - "%s timed out at ofset %llx [%llx - %llx]\n", + "%s timed out at offset %llx [%llx - %llx]\n", __func__, addr, hole_start, hole_end)) { err = -EINTR; break; @@ -1011,7 +1014,7 @@ static int shrink_boom(struct i915_address_space *vm, /* * Catch the case which shrink_hole seems to miss. The setup here * requires invoking the shrinker as we do the alloc_pt/alloc_pd, while - * ensuring that all vma assiocated with the respective pd/pdp are + * ensuring that all vma associated with the respective pd/pdp are * unpinned at the time. */ @@ -1537,9 +1540,10 @@ static int igt_gtt_reserve(void *arg) u64 total; int err = -ENODEV; - /* i915_gem_gtt_reserve() tries to reserve the precise range + /* + * i915_gem_gtt_reserve() tries to reserve the precise range * for the node, and evicts if it has to. So our test checks that - * it can give us the requsted space and prevent overlaps. + * it can give us the requested space and prevent overlaps. */ /* Start by filling the GGTT */ @@ -1743,7 +1747,8 @@ static int igt_gtt_insert(void *arg) u64 total; int err = -ENODEV; - /* i915_gem_gtt_insert() tries to allocate some free space in the GTT + /* + * i915_gem_gtt_insert() tries to allocate some free space in the GTT * to the node, evicting if required. */ diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 71b52d5efef4..7c4111e60f2e 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -159,7 +159,8 @@ static int igt_vma_create(void *arg) LIST_HEAD(objects); int err = -ENOMEM; - /* Exercise creating many vma amonst many objections, checking the + /* + * Exercise creating many vma amongst many objections, checking the * vma creation and lookup routines. */ @@ -292,7 +293,8 @@ static int igt_vma_pin1(void *arg) VALID(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)), #if !IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) - /* Misusing BIAS is a programming error (it is not controllable + /* + * Misusing BIAS is a programming error (it is not controllable * from userspace) so when debugging is enabled, it explodes. * However, the tests are still quite interesting for checking * variable start, end and size. @@ -312,7 +314,8 @@ static int igt_vma_pin1(void *arg) struct i915_vma *vma; int err = -EINVAL; - /* Exercise all the weird and wonderful i915_vma_pin requests, + /* + * Exercise all the weird and wonderful i915_vma_pin requests, * focusing on error handling of boundary conditions. */ @@ -577,7 +580,8 @@ static int igt_vma_rotate_remap(void *arg) const unsigned int max_pages = 64; int err = -ENOMEM; - /* Create VMA for many different combinations of planes and check + /* + * Create VMA for many different combinations of planes and check * that the page layout within the rotated VMA match our expectations. */ @@ -804,7 +808,8 @@ static int igt_vma_partial(void *arg) struct i915_vma *vma; int err = -ENOMEM; - /* Create lots of different VMA for the object and check that + /* + * Create lots of different VMA for the object and check that * we are returned the same VMA when we later request the same range. */ -- cgit v1.2.3-59-g8ed1b From 5b056be1f2d6d9ec3c61cc7b6e4c2cebd094f9f9 Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:15 +0530 Subject: drm/i915/soc: fix typos in i915/soc files Fix all typos in files under drm/i915/soc reported by codespell tool. Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-7-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/soc/intel_pch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/soc/intel_pch.c b/drivers/gpu/drm/i915/soc/intel_pch.c index 842db43e46c0..9f7c9dbc178e 100644 --- a/drivers/gpu/drm/i915/soc/intel_pch.c +++ b/drivers/gpu/drm/i915/soc/intel_pch.c @@ -243,7 +243,7 @@ void intel_detect_pch(struct drm_i915_private *dev_priv) * underneath. This is a requirement from virtualization team. * * In some virtualized environments (e.g. XEN), there is irrelevant - * ISA bridge in the system. To work reliably, we should scan trhough + * ISA bridge in the system. To work reliably, we should scan through * all the ISA bridge devices and check for the first match, instead * of only checking the first one. */ -- cgit v1.2.3-59-g8ed1b From c55af0065207472ce96492e282d566c3415f3288 Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:16 +0530 Subject: drm/i915/display: fix typos in i915/display files Fix all typos in files under drm/i915/display reported by codespell tool. v2: - Include british and american spelling, as those are not typos. - Fix commenting style. v3: Fix "In case" wrongly capitalized and also fix comment style. Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-8-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/dvo_ns2501.c | 2 +- drivers/gpu/drm/i915/display/i9xx_wm.c | 6 +-- drivers/gpu/drm/i915/display/icl_dsi.c | 4 +- drivers/gpu/drm/i915/display/intel_audio.c | 4 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_color.c | 2 +- drivers/gpu/drm/i915/display/intel_crt.c | 6 ++- drivers/gpu/drm/i915/display/intel_crtc.c | 2 +- drivers/gpu/drm/i915/display/intel_cursor.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 4 +- drivers/gpu/drm/i915/display/intel_display.c | 8 ++-- .../gpu/drm/i915/display/intel_display_debugfs.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power.c | 4 +- .../drm/i915/display/intel_display_power_well.h | 4 +- drivers/gpu/drm/i915/display/intel_display_types.h | 4 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- .../gpu/drm/i915/display/intel_dp_link_training.c | 4 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 +- drivers/gpu/drm/i915/display/intel_dp_test.c | 4 +- drivers/gpu/drm/i915/display/intel_dp_tunnel.c | 2 +- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 2 +- drivers/gpu/drm/i915/display/intel_dsb.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 2 +- drivers/gpu/drm/i915/display/intel_dvo_dev.h | 2 +- drivers/gpu/drm/i915/display/intel_fdi.c | 2 +- drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 2 +- drivers/gpu/drm/i915/display/intel_frontbuffer.c | 2 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 8 ++-- drivers/gpu/drm/i915/display/intel_hotplug.c | 6 +-- drivers/gpu/drm/i915/display/intel_hotplug_irq.c | 2 +- drivers/gpu/drm/i915/display/intel_link_bw.c | 2 +- drivers/gpu/drm/i915/display/intel_overlay.c | 20 +++++---- drivers/gpu/drm/i915/display/intel_pmdemand.c | 2 +- drivers/gpu/drm/i915/display/intel_pps.c | 5 ++- drivers/gpu/drm/i915/display/intel_psr.c | 8 ++-- drivers/gpu/drm/i915/display/intel_sdvo.c | 4 +- drivers/gpu/drm/i915/display/intel_sdvo_regs.h | 2 +- drivers/gpu/drm/i915/display/intel_snps_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_vblank.c | 2 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 2 +- drivers/gpu/drm/i915/display/skl_scaler.c | 48 +++++++++++----------- drivers/gpu/drm/i915/display/skl_universal_plane.c | 4 +- drivers/gpu/drm/i915/display/skl_watermark.c | 4 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 2 +- 47 files changed, 112 insertions(+), 103 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/dvo_ns2501.c b/drivers/gpu/drm/i915/display/dvo_ns2501.c index 686393dfbbf5..04005cdd0461 100644 --- a/drivers/gpu/drm/i915/display/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/display/dvo_ns2501.c @@ -517,7 +517,7 @@ static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo) * Even if not, the detection bit of the 2501 is unreliable as * it only works for some display types. * It is even more unreliable as the PLL must be active for - * allowing reading from the chiop. + * allowing reading from the chip. */ return connector_status_connected; } diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index db78c1e6b0a3..497850a6ac81 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -446,7 +446,7 @@ static const struct intel_watermark_params i845_wm_info = { * @latency: Memory wakeup latency in 0.1us units * * Compute the watermark using the method 1 or "small buffer" - * formula. The caller may additonally add extra cachelines + * formula. The caller may additionally add extra cachelines * to account for TLB misses and clock crossings. * * This method is concerned with the short term drain rate @@ -493,7 +493,7 @@ static unsigned int intel_wm_method1(unsigned int pixel_rate, * @latency: Memory wakeup latency in 0.1us units * * Compute the watermark using the method 2 or "large buffer" - * formula. The caller may additonally add extra cachelines + * formula. The caller may additionally add extra cachelines * to account for TLB misses and clock crossings. * * This method is concerned with the long term drain rate @@ -1562,7 +1562,7 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) /* * When enabling sprite0 after sprite1 has already been enabled * we tend to get an underrun unless sprite0 already has some - * FIFO space allcoated. Hence we always allocate at least one + * FIFO space allocated. Hence we always allocate at least one * cacheline for sprite0 whenever sprite1 is enabled. * * All other plane enable sequences appear immune to this problem. diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index c977b74f82f0..3bedaf1454b1 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -243,7 +243,7 @@ static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder) for_each_dsi_phy(phy, intel_dsi->phys) { /* * Program voltage swing and pre-emphasis level values as per - * table in BSPEC under DDI buffer programing + * table in BSPEC under DDI buffer programming. */ mask = SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK; val = SCALING_MODE_SEL(0x2) | TAP2_DISABLE | TAP3_DISABLE | @@ -961,7 +961,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); /* - * FIXME: Programing this by assuming progressive mode, since + * FIXME: Programming this by assuming progressive mode, since * non-interlaced info from VBT is not saved inside * struct drm_display_mode. * For interlace mode: program required pixel minus 2 diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 4b1f46815ad5..113d763e6ef3 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -567,7 +567,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, AUDIO_ELD_VALID(cpu_transcoder), 0); /* - * The audio componenent is used to convey the ELD + * The audio component is used to convey the ELD * instead using of the hardware ELD buffer. */ @@ -665,7 +665,7 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder, IBX_ELD_VALID(port), 0); /* - * The audio componenent is used to convey the ELD + * The audio component is used to convey the ELD * instead using of the hardware ELD buffer. */ diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index bee90b06995a..b520231833b7 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2250,7 +2250,7 @@ static void bxt_sanitize_cdclk(struct intel_display *display) /* * Let's ignore the pipe field, since BIOS could have configured the - * dividers both synching to an active pipe, or asynchronously + * dividers both syncing to an active pipe, or asynchronously * (PIPE_NONE). */ cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE); diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 2f51eccdb27a..8400a97f7e43 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -998,7 +998,7 @@ static void skl_color_commit_noarm(struct intel_dsb *dsb, * output all black (until CSC_MODE is rearmed and properly latched). * Once PSR exit (and proper register latching) has occurred the * danger is over. Thus when PSR is enabled the CSC coeff/offset - * register programming will be peformed from skl_color_commit_arm() + * register programming will be performed from skl_color_commit_arm() * which is called after PSR exit. */ if (!crtc_state->has_psr) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 4634d3fd9f20..bc724dc5b4ea 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -745,8 +745,10 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) transconf | TRANSCONF_FORCE_BORDER); intel_de_posting_read(display, TRANSCONF(display, cpu_transcoder)); - /* Wait for next Vblank to substitue - * border color for Color info */ + /* + * Wait for next Vblank to substitute + * border color for Color info. + */ intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(display, pipe)); st00 = intel_de_read8(display, _VGA_MSR_WRITE); status = ((st00 & (1 << 4)) != 0) ? diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 3e8b52eaac27..e69b28779ac5 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -96,7 +96,7 @@ u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); /* - * From Gen 11, In case of dsi cmd mode, frame counter wouldnt + * From Gen 11, in case of dsi cmd mode, frame counter wouldn't * have updated at the beginning of TE, if we want to use * the hw counter, then we would find it updated in only * the next TE, hence switching to sw counter. diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index ae7243ad6e0c..48c3d212f690 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -680,7 +680,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb, * CURPOS. * * On other platforms CURPOS always requires the - * CURBASE write to arm the update. Additonally + * CURBASE write to arm the update. Additionally * a write to any of the cursor register will cancel * an already armed cursor update. Thus leaving out * the CURBASE write after CURPOS could lead to a diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3693b36b9336..05df8f986491 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2984,7 +2984,7 @@ static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state, * - crtc_state will be the state of the first stream to be activated on this * port, and it may not be the same stream that will be deactivated last, but * each stream should have a state that is identical when it comes to the DP - * link parameteres + * link parameters. */ static void intel_ddi_pre_enable(struct intel_atomic_state *state, struct intel_encoder *encoder, @@ -3284,7 +3284,7 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, * be deactivated on this port, and it may not be the same * stream that was activated last, but each stream * should have a state that is identical when it comes to - * the DP link parameteres + * the DP link parameters */ if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 10550bc0778e..7d68d652c1bc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1013,7 +1013,7 @@ static void intel_async_flip_vtd_wa(struct drm_i915_private *i915, { if (DISPLAY_VER(i915) == 9) { /* - * "Plane N strech max must be programmed to 11b (x1) + * "Plane N stretch max must be programmed to 11b (x1) * when Async flips are enabled on that plane." */ intel_de_rmw(i915, CHICKEN_PIPESL_1(pipe), @@ -3592,7 +3592,7 @@ static void ilk_get_pfit_config(struct intel_crtc_state *crtc_state) REG_FIELD_GET(PF_WIN_YSIZE_MASK, size)); /* - * We currently do not free assignements of panel fitters on + * We currently do not free assignments of panel fitters on * ivb/hsw (since we don't use the higher upscaling modes which * differentiates them) so just WARN about this case for now. */ @@ -4292,7 +4292,7 @@ int intel_dotclock_calculate(int link_freq, /* * The calculation for the data clock -> pixel clock is: * pixel_clock = ((m/n)*(link_clock * nr_lanes))/bpp - * But we want to avoid losing precison if possible, so: + * But we want to avoid losing precision if possible, so: * pixel_clock = ((m * link_clock * nr_lanes)/(n*bpp)) * * and for link freq (10kbs units) -> pixel clock it is: @@ -6433,7 +6433,7 @@ static void kill_joiner_secondaries(struct intel_atomic_state *state, * the intel_crtc_enable_flip_done() function. * * As soon as the surface address register is written, flip done interrupt is - * generated and the requested events are sent to the usersapce in the interrupt + * generated and the requested events are sent to the userspace in the interrupt * handler itself. The timestamp and sequence sent during the flip done event * correspond to the last vblank and have no relation to the actual time when * the flip done event was sent. diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index f1d76484025a..926f09c35084 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -940,7 +940,7 @@ static int i915_lpsp_capability_show(struct seq_file *m, void *data) /* * Actually TGL can drive LPSP on port till DDI_C * but there is no physical connected DDI_C on TGL sku's, - * even driver is not initilizing DDI_C port for gen12. + * even driver is not initializing DDI_C port for gen12. */ lpsp_capable = encoder->port <= PORT_B; else if (DISPLAY_VER(i915) == 11) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 8e86fcbcc189..14ae60749f02 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -842,7 +842,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, * block right away if this is the last reference. * * This function is only for the power domain code's internal use to suppress wakeref - * tracking when the correspondig debug kconfig option is disabled, should not + * tracking when the corresponding debug kconfig option is disabled, should not * be used otherwise. */ void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv, @@ -1733,7 +1733,7 @@ static void icl_display_core_uninit(struct intel_display *display) gen9_disable_dc_states(display); intel_dmc_disable_program(display); - /* 1. Disable all display engine functions -> aready done */ + /* 1. Disable all display engine functions -> already done */ /* 2. Disable DBUF */ gen9_dbuf_disable(display); diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h index 338379dae44c..ec8e508d0593 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.h +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -60,7 +60,7 @@ struct i915_power_well_instance { /* unique identifier for this power well */ enum i915_power_well_id id; /* - * Arbitraty data associated with this power well. Platform and power + * Arbitrary data associated with this power well. Platform and power * well specific. */ union { @@ -77,7 +77,7 @@ struct i915_power_well_instance { struct { /* * request/status flag index in the power well - * constrol/status registers. + * control/status registers. */ u8 idx; } hsw; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 083eb86f0904..96429201b8a0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -732,7 +732,7 @@ struct intel_crtc_scaler_state { * * intel_atomic_setup_scalers will setup available scalers to users * requesting scalers. It will gracefully fail if request exceeds - * avilability. + * availability. */ #define SKL_CRTC_INDEX 31 unsigned scaler_users; @@ -1113,7 +1113,7 @@ struct intel_crtc_state { u16 su_y_granularity; /* - * Frequence the dpll for the port should run at. Differs from the + * Frequency the dpll for the port should run at. Differs from the * adjusted dotclock e.g. for DP or 10/12bpc hdmi mode. This is also * already multiplied by pixel_multiplier. */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9ec23860b593..c239008658a8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1075,7 +1075,7 @@ static bool source_can_output(struct intel_dp *intel_dp, /* * No YCbCr output support on gmch platforms. * Also, ILK doesn't seem capable of DP YCbCr output. - * The displayed image is severly corrupted. SNB+ is fine. + * The displayed image is severely corrupted. SNB+ is fine. */ return !HAS_GMCH(display) && !display->platform.ironlake; diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 8b1977cfec50..9cb22baafeeb 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -783,7 +783,7 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp, /* * WaEdpLinkRateDataReload * - * Parade PS8461E MUX (used on varius TGL+ laptops) needs + * Parade PS8461E MUX (used on various TGL+ laptops) needs * to snoop the link rates reported by the sink when we * use LINK_RATE_SET in order to operate in jitter cleaning * mode (as opposed to redriver mode). Unfortunately it @@ -1629,7 +1629,7 @@ void intel_dp_start_link_train(struct intel_atomic_state *state, /* * Ignore the link failure in CI * - * In fixed enviroments like CI, sometimes unexpected long HPDs are + * In fixed environments like CI, sometimes unexpected long HPDs are * generated by the displays. If ignore_long_hpd flag is set, such long * HPDs are ignored. And probably as a consequence of these ignored * long HPDs, subsequent link trainings are failed resulting into CI diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index fbfc756368b8..7c1de9aeeacc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -837,7 +837,7 @@ static int intel_dp_mst_check_bw(struct intel_atomic_state *state, * @state must be recomputed with the updated @limits. * * Returns: - * - 0 if the confugration is valid + * - 0 if the configuration is valid * - %-EAGAIN, if the configuration is invalid and @limits got updated * with fallback values with which the configuration of all CRTCs in * @state must be recomputed @@ -2052,7 +2052,7 @@ bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state, * @intel_dp: DP port object * * Prepare an MST link for topology probing, programming the target - * link parameters to DPCD. This step is a requirement of the enumaration + * link parameters to DPCD. This step is a requirement of the enumeration * of path resources during probing. */ void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp) diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c b/drivers/gpu/drm/i915/display/intel_dp_test.c index 380b359b0420..614b90d6938f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_test.c +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c @@ -257,7 +257,7 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp, /* * FIXME: Ideally pattern should come from DPCD 0x250. As * current firmware of DPR-100 could not set it, so hardcoding - * now for complaince test. + * now for compliance test. */ drm_dbg_kms(display->drm, "Set 80Bit Custom Phy Test Pattern 0x3e0f83e0 0x0f83e0f8 0x0000f83e\n"); @@ -275,7 +275,7 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp, /* * FIXME: Ideally pattern should come from DPCD 0x24A. As * current firmware of DPR-100 could not set it, so hardcoding - * now for complaince test. + * now for compliance test. */ drm_dbg_kms(display->drm, "Set HBR2 compliance Phy Test Pattern\n"); diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c index 589872babdd7..280f302967e3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c +++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c @@ -647,7 +647,7 @@ void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state, * @state must be recomputed with the updated @limits. * * Returns: - * - 0 if the confugration is valid + * - 0 if the configuration is valid * - %-EAGAIN, if the configuration is invalid and @limits got updated * with fallback values with which the configuration of all CRTCs in * @state must be recomputed diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 52a36a2281e6..5f88702818d3 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -40,7 +40,7 @@ * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI * ports. DPIO is the name given to such a display PHY. These PHYs * don't follow the standard programming model using direct MMIO - * registers, and instead their registers must be accessed trough IOSF + * registers, and instead their registers must be accessed through IOSF * sideband. VLV has one such PHY for driving ports B and C, and CHV * adds another PHY for driving port D. Each PHY responds to specific * IOSF-SB port. diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index d86cc9ffd4ac..b8fa04d3cd5c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4372,7 +4372,7 @@ void intel_shared_dpll_init(struct drm_i915_private *i915) * calling intel_shared_dpll_swap_state(). * * Returns: - * 0 on success, negative error code on falure. + * 0 on success, negative error code on failure. */ int intel_compute_shared_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 6af325b8e27d..3eee76874304 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -318,7 +318,7 @@ struct dpll_info { const struct intel_shared_dpll_funcs *funcs; /** - * @id: unique indentifier for this DPLL + * @id: unique identifier for this DPLL */ enum intel_dpll_id id; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 89d3496bcbdb..2f2812c23972 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -821,7 +821,7 @@ void intel_dsb_irq_handler(struct intel_display *display, if (crtc->dsb_event) { /* - * Update vblank counter/timestmap in case it + * Update vblank counter/timestamp in case it * hasn't been done yet for this frame. */ drm_crtc_accurate_vblank_count(&crtc->base); diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index b2b78f39cfd3..7b2ffd14ae6e 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -582,7 +582,7 @@ static const fn_mipi_elem_exec exec_elem[] = { /* * MIPI Sequence from VBT #53 parsing logic - * We have already separated each seqence during bios parsing + * We have already separated each sequence during bios parsing * Following is generic execution function for any sequence */ diff --git a/drivers/gpu/drm/i915/display/intel_dvo_dev.h b/drivers/gpu/drm/i915/display/intel_dvo_dev.h index 4bf476656b8c..3be1a16cac20 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo_dev.h +++ b/drivers/gpu/drm/i915/display/intel_dvo_dev.h @@ -57,7 +57,7 @@ struct intel_dvo_dev_ops { * Turn on/off output. * * Because none of our dvo drivers support an intermediate power levels, - * we don't expose this in the interfac. + * we don't expose this in the interface. */ void (*dpms)(struct intel_dvo_device *dvo, bool enable); diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 37cdfa9c692a..3e8d6d8af780 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -390,7 +390,7 @@ static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state, * @state must be recomputed with the updated @limits. * * Returns: - * - 0 if the confugration is valid + * - 0 if the configuration is valid * - %-EAGAIN, if the configuration is invalid and @limits got updated * with fallback values with which the configuration of all CRTCs * in @state must be recomputed diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c index cda1daf4cdea..18fcdbe1248a 100644 --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c @@ -290,7 +290,7 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, } /** - * intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state + * intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrun reporting state * @dev_priv: i915 device instance * @pipe: (CPU) pipe to set state for * @enable: whether underruns should be reported or not diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 6ed5f726ee60..26128c610cb4 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -227,7 +227,7 @@ static void intel_frontbuffer_flush_work(struct work_struct *work) * @front: GEM object to flush * * This function is targeted for our dirty callback for queueing flush when - * dma fence is signales + * dma fence is signals */ void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front) { diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 1bab7c34a794..7cc0399b2a5d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -353,7 +353,7 @@ static bool hdcp_key_loadable(struct intel_display *display) /* * Another req for hdcp key loadability is enabled state of pll for - * cdclk. Without active crtc we wont land here. So we are assuming that + * cdclk. Without active crtc we won't land here. So we are assuming that * cdclk is already on. */ @@ -1550,9 +1550,9 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) * with a 50ms delay if not hdcp2 capable for DP/DPMST encoders * (dock decides to stop advertising hdcp2 capability for some reason). * The reason being that during suspend resume dock usually keeps the - * HDCP2 registers inaccesible causing AUX error. This wouldn't be a + * HDCP2 registers inaccessible causing AUX error. This wouldn't be a * big problem if the userspace just kept retrying with some delay while - * it continues to play low value content but most userpace applications + * it continues to play low value content but most userspace applications * end up throwing an error when it receives one from KMD. This makes * sure we give the dock and the sink devices to complete its power cycle * and then try HDCP authentication. The values of 10 and delay of 50ms @@ -2573,7 +2573,7 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, /* * During the HDCP encryption session if Type change is requested, - * disable the HDCP and reenable it with new TYPE value. + * disable the HDCP and re-enable it with new TYPE value. */ if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED || diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 3adc791d3776..c0d48f651dab 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -806,7 +806,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work) * of the powerwells. * * Since this function can get called in contexts where we're already holding - * dev->mode_config.mutex, we do the actual hotplug enabling in a seperate + * dev->mode_config.mutex, we do the actual hotplug enabling in a separate * worker. * * Also see: intel_hpd_init() and intel_hpd_poll_disable(). @@ -823,7 +823,7 @@ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv) /* * We might already be holding dev->mode_config.mutex, so do this in a - * seperate worker + * separate worker * As well, there's no issue if we race here since we always reschedule * this worker anyway */ @@ -844,7 +844,7 @@ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv) * of the powerwells. * * Since this function can get called in contexts where we're already holding - * dev->mode_config.mutex, we do the actual hotplug enabling in a seperate + * dev->mode_config.mutex, we do the actual hotplug enabling in a separate * worker. * * Also used during driver init to initialize connector->polled diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c index 476ac88087e0..2137ac7b882a 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c @@ -197,7 +197,7 @@ void i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, * @bits: bits to enable * NOTE: the HPD enable bits are modified both inside and outside * of an interrupt context. To avoid that read-modify-write cycles - * interfer, these bits are protected by a spinlock. Since this + * interfere, these bits are protected by a spinlock. Since this * function is usually not called from a context where the lock is * held already, this function acquires the lock itself. A non-locking * version is also available. diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c index 29705c159119..f4d60e77aa18 100644 --- a/drivers/gpu/drm/i915/display/intel_link_bw.c +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c @@ -221,7 +221,7 @@ assert_link_limit_change_valid(struct intel_display *display, * limits in @new_limits if there is a BW limitation. * * Returns: - * - 0 if the confugration is valid + * - 0 if the configuration is valid * - %-EAGAIN, if the configuration is invalid and @new_limits got updated * with fallback values with which the configuration of all CRTCs * in @state must be recomputed diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index ca30fff61876..bbb0db33740e 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -46,7 +46,8 @@ /* Limits for overlay size. According to intel doc, the real limits are: * Y width: 4095, UV width (planar): 2047, Y height: 2047, * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use - * the mininum of both. */ + * the minimum of both. + */ #define IMAGE_MAX_WIDTH 2048 #define IMAGE_MAX_HEIGHT 2046 /* 2 * 1023 */ /* on 830 and 845 these large limits result in the card hanging */ @@ -408,10 +409,12 @@ static int intel_overlay_off(struct intel_overlay *overlay) drm_WARN_ON(display->drm, !overlay->active); - /* According to intel docs the overlay hw may hang (when switching + /* + * According to intel docs the overlay hw may hang (when switching * off) without loading the filter coeffs. It is however unclear whether * this applies to the disabling of the overlay or to the switching off - * of the hw. Do it in both cases */ + * of the hw. Do it in both cases. + */ flip_addr |= OFC_UPDATE; rq = alloc_request(overlay, intel_overlay_off_tail); @@ -442,16 +445,19 @@ static int intel_overlay_off(struct intel_overlay *overlay) return i915_active_wait(&overlay->last_flip); } -/* recover from an interruption due to a signal - * We have to be careful not to repeat work forever an make forward progess. */ +/* + * Recover from an interruption due to a signal. + * We have to be careful not to repeat work forever an make forward progress. + */ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) { return i915_active_wait(&overlay->last_flip); } -/* Wait for pending overlay flip and release old frame. +/* + * Wait for pending overlay flip and release old frame. * Needs to be called before the overlay register are changed - * via intel_overlay_(un)map_regs + * via intel_overlay_(un)map_regs. */ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) { diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 975520322136..63301a01906c 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -609,7 +609,7 @@ intel_pmdemand_program_params(struct intel_display *display, goto unlock; drm_dbg_kms(display->drm, - "initate pmdemand request values: (0x%x 0x%x)\n", + "initiate pmdemand request values: (0x%x 0x%x)\n", mod_reg1, mod_reg2); intel_de_rmw(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0, diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index eb35f0249f2b..c0f65749a3f6 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -1501,8 +1501,9 @@ static void pps_init_delays_vbt(struct intel_dp *intel_dp, if (!pps_delays_valid(vbt)) return; - /* On Toshiba Satellite P50-C-18C system the VBT T12 delay - * of 500ms appears to be too short. Ocassionally the panel + /* + * On Toshiba Satellite P50-C-18C system the VBT T12 delay + * of 500ms appears to be too short. Occasionally the panel * just fails to power back on. Increasing the delay to 800ms * seems sufficient to avoid this problem. */ diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index aa6ff057b54c..2bdb6c9c2283 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -154,7 +154,7 @@ * * Unfortunately CHICKEN_TRANS itself seems to be double buffered * and thus won't latch until the first vblank. So with DC states - * enabled the register effctively uses the reset value during DC5 + * enabled the register effectively uses the reset value during DC5 * exit+PSR exit sequence, and thus the bit does nothing until * latched by the vblank that it was trying to prevent from being * generated in the first place. So we should probably call this @@ -171,7 +171,7 @@ * CHICKEN_PIPESL_1[15]/HSW_UNMASK_VBL_TO_REGS_IN_SRD (hsw): * * On BDW without this bit is no vblanks whatsoever are - * generated after PSR exit. On HSW this has no apparant effect. + * generated after PSR exit. On HSW this has no apparent effect. * WaPsrDPRSUnmaskVBlankInSRD says to set this. * * The rest of the bits are more self-explanatory and/or @@ -185,7 +185,7 @@ * has_psr + has_panel_replay: Panel Replay * has_psr + has_panel_replay + has_sel_update: Panel Replay Selective Update * - * Description of some intel_psr varibles. enabled, panel_replay_enabled, + * Description of some intel_psr variables. enabled, panel_replay_enabled, * sel_update_enabled * * enabled (alone): PSR1 @@ -1050,7 +1050,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) }; /* * Still using the default IO_BUFFER_WAKE and FAST_WAKE, see - * comments bellow for more information + * comments below for more information */ int tmp; diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 498b35ec4e0f..c78da5a2b559 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1741,8 +1741,8 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, * pixel multiplier readout is tricky: Only on i915g/gm it is stored in * the sdvo port register, on all other platforms it is part of the dpll * state. Since the general pipe state readout happens before the - * encoder->get_config we so already have a valid pixel multplier on all - * other platfroms. + * encoder->get_config we so already have a valid pixel multiplier on all + * other platforms. */ if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { pipe_config->pixel_multiplier = diff --git a/drivers/gpu/drm/i915/display/intel_sdvo_regs.h b/drivers/gpu/drm/i915/display/intel_sdvo_regs.h index 54f099abefeb..56c4551abefd 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/display/intel_sdvo_regs.h @@ -244,7 +244,7 @@ struct intel_sdvo_set_target_input_args { * Takes a struct intel_sdvo_output_flags of which outputs are targeted by * future output commands. * - * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], + * Affected commands include SET_OUTPUT_TIMINGS_PART[12], * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. */ #define SDVO_CMD_SET_TARGET_OUTPUT 0x11 diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index ec3c0ea2f4cb..353221d3e29f 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -522,7 +522,7 @@ static const struct intel_mpllb_state dg2_hdmi_148_5 = { REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), }; -/* values in the below table are calculted using the algo */ +/* values in the below table are calculated using the algo */ static const struct intel_mpllb_state dg2_hdmi_25200 = { .clock = 25200, .ref_control = diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index fb80e0bef08a..4efd4f7d497a 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -369,7 +369,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, /* * Already exiting vblank? If so, shift our position - * so it looks like we're already apporaching the full + * so it looks like we're already approaching the full * vblank end. This should make the generated timestamp * more or less match when the active portion will start. */ diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 1e8f71fb3094..932435a7f88d 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -106,7 +106,7 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg) * According to DSC 1.2 spec in Section 4.1 if native_420 is set: * -second_line_bpg_offset is 12 in general and equal to 2*(slice_height-1) if slice * height < 8. - * -second_line_offset_adj is 512 as shown by emperical values to yield best chroma + * -second_line_offset_adj is 512 as shown by empirical values to yield best chroma * preservation in second line. * -nsl_bpg_offset is calculated as second_line_offset/slice_height -1 then rounded * up to 16 fractional bits, we left shift second line offset by 11 to preserve 11 diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index a11e09a15e23..515196e03b93 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -585,31 +585,31 @@ static u16 glk_nearest_filter_coef(int t) * The letter represents the filter tap (D is the center tap) and the number * represents the coefficient set for a phase (0-16). * - * +------------+------------------------+------------------------+ - * |Index value | Data value coeffient 1 | Data value coeffient 2 | - * +------------+------------------------+------------------------+ - * | 00h | B0 | A0 | - * +------------+------------------------+------------------------+ - * | 01h | D0 | C0 | - * +------------+------------------------+------------------------+ - * | 02h | F0 | E0 | - * +------------+------------------------+------------------------+ - * | 03h | A1 | G0 | - * +------------+------------------------+------------------------+ - * | 04h | C1 | B1 | - * +------------+------------------------+------------------------+ - * | ... | ... | ... | - * +------------+------------------------+------------------------+ - * | 38h | B16 | A16 | - * +------------+------------------------+------------------------+ - * | 39h | D16 | C16 | - * +------------+------------------------+------------------------+ - * | 3Ah | F16 | C16 | - * +------------+------------------------+------------------------+ - * | 3Bh | Reserved | G16 | - * +------------+------------------------+------------------------+ + * +------------+--------------------------+--------------------------+ + * |Index value | Data value coefficient 1 | Data value coefficient 2 | + * +------------+--------------------------+--------------------------+ + * | 00h | B0 | A0 | + * +------------+--------------------------+--------------------------+ + * | 01h | D0 | C0 | + * +------------+--------------------------+--------------------------+ + * | 02h | F0 | E0 | + * +------------+--------------------------+--------------------------+ + * | 03h | A1 | G0 | + * +------------+--------------------------+--------------------------+ + * | 04h | C1 | B1 | + * +------------+--------------------------+--------------------------+ + * | ... | ... | ... | + * +------------+--------------------------+--------------------------+ + * | 38h | B16 | A16 | + * +------------+--------------------------+--------------------------+ + * | 39h | D16 | C16 | + * +------------+--------------------------+--------------------------+ + * | 3Ah | F16 | C16 | + * +------------+--------------------------+--------------------------+ + * | 3Bh | Reserved | G16 | + * +------------+--------------------------+--------------------------+ * - * To enable nearest-neighbor scaling: program scaler coefficents with + * To enable nearest-neighbor scaling: program scaler coefficients with * the center tap (Dxx) values set to 1 and all other values set to 0 as per * SCALER_COEFFICIENT_FORMAT * diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 450dd8c64e0c..301ad3a22c4c 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1099,7 +1099,7 @@ static u32 skl_plane_ctl_rotate(unsigned int rotate) break; /* * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr - * while i915 HW rotation is clockwise, thats why this swapping. + * while i915 HW rotation is clockwise, that's why this swapping. */ case DRM_MODE_ROTATE_90: return PLANE_CTL_ROTATE_270; @@ -2997,7 +2997,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, /* * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr - * while i915 HW rotation is clockwise, thats why this swapping. + * while i915 HW rotation is clockwise, that's why this swapping. */ switch (val & PLANE_CTL_ROTATE_MASK) { case PLANE_CTL_ROTATE_0: diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index f4458d1185b3..2bc6251e93d6 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -584,7 +584,7 @@ u32 skl_ddb_dbuf_slice_mask(struct drm_i915_private *i915, /* * Per plane DDB entry can in a really worst case be on multiple slices - * but single entry is anyway contigious. + * but single entry is anyway contiguous. */ while (start_slice <= end_slice) { slice_mask |= BIT(start_slice); @@ -3204,7 +3204,7 @@ adjust_wm_latency(struct drm_i915_private *i915, * WaWmMemoryReadLatency * * punit doesn't take into account the read latency so we need - * to add proper adjustement to each valid level we retrieve + * to add proper adjustment to each valid level we retrieve * from the punit when level 0 response data is 0us. */ if (wm[0] == 0) { diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index d49e9b3c7627..0333c4d9b703 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -59,7 +59,7 @@ static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count, 8 * 100), lane_count); } -/* return pixels equvalent to txbyteclkhs */ +/* return pixels equivalent to txbyteclkhs */ static u16 pixels_from_txbyteclkhs(u16 clk_hs, int bpp, int lane_count, u16 burst_mode_ratio) { diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 59a50647f2c3..ac69eaece0fd 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -459,7 +459,7 @@ static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port, /* * rx divider value needs to be updated in the - * two differnt bit fields in the register hence splitting the + * two different bit fields in the register hence splitting the * rx divider value accordingly */ rx_div_lower = rx_div & RX_DIVIDER_BIT_1_2; -- cgit v1.2.3-59-g8ed1b From 381ab12d483ea30af4ca52db51d23c947f2904c1 Mon Sep 17 00:00:00 2001 From: Nitin Gote Date: Mon, 20 Jan 2025 13:45:17 +0530 Subject: drm/i915: fix typos in drm/i915 files Fix all typos in files under drm/i915 reported by codespell tool. v2: Fix commenting style. v3: "in case" should be capitalized and fix comment style. Signed-off-by: Nitin Gote Reviewed-by: Krzysztof Niemiec Link: https://patchwork.freedesktop.org/patch/msgid/20250120081517.3237326-9-nitin.r.gote@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 6 +++--- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/i915_module.c | 2 +- drivers/gpu/drm/i915/i915_perf.c | 19 ++++++++++++------- drivers/gpu/drm/i915/i915_pmu.h | 2 +- drivers/gpu/drm/i915/i915_reg.h | 7 ++++--- drivers/gpu/drm/i915/i915_request.c | 2 +- drivers/gpu/drm/i915/i915_request.h | 4 ++-- drivers/gpu/drm/i915/i915_vma.c | 8 ++++---- drivers/gpu/drm/i915/intel_clock_gating.c | 2 +- drivers/gpu/drm/i915/intel_gvt.c | 2 +- drivers/gpu/drm/i915/intel_gvt_mmio_table.c | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.h | 2 +- drivers/gpu/drm/i915/intel_uncore.c | 2 +- 16 files changed, 36 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c2ae37d6b94d..91a7748f4492 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1130,7 +1130,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) * leave the device in D0 on those platforms and hope the BIOS will * power down the device properly. The issue was seen on multiple old * GENs with different BIOS vendors, so having an explicit blacklist - * is inpractical; apply the workaround on everything pre GEN6. The + * is impractical; apply the workaround on everything pre GEN6. The * platforms where the issue was seen: * Lenovo Thinkpad X301, X61s, X60, T60, X41 * Fujitsu FSC S7110 diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 070ab6546987..8c8d43451f35 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1146,11 +1146,11 @@ int i915_gem_init(struct drm_i915_private *dev_priv) int ret; /* - * In the proccess of replacing cache_level with pat_index a tricky + * In the process of replacing cache_level with pat_index a tricky * dependency is created on the definition of the enum i915_cache_level. - * in case this enum is changed, PTE encode would be broken. + * In case this enum is changed, PTE encode would be broken. * Add a WARNING here. And remove when we completely quit using this - * enum + * enum. */ BUILD_BUG_ON(I915_CACHE_NONE != 0 || I915_CACHE_LLC != 1 || diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 202eb1b6ae54..f98e5cc14724 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1233,7 +1233,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv) } /** - * intel_irq_uninstall - finilizes all irq handling + * intel_irq_uninstall - finalizes all irq handling * @dev_priv: i915 device instance * * This stops interrupt and hotplug handling and unregisters and frees all diff --git a/drivers/gpu/drm/i915/i915_module.c b/drivers/gpu/drm/i915/i915_module.c index 7ed6d70389af..2f88970cc0a9 100644 --- a/drivers/gpu/drm/i915/i915_module.c +++ b/drivers/gpu/drm/i915/i915_module.c @@ -24,7 +24,7 @@ static int i915_check_nomodeset(void) bool use_kms = true; /* - * Enable KMS by default, unless explicitly overriden by + * Enable KMS by default, unless explicitly overridden by * either the i915.modeset parameter or by the * nomodeset boot option. */ diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 2406cda75b7b..eb7b4e21b124 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -548,7 +548,8 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream) bool pollin; u32 partial_report_size; - /* We have to consider the (unlikely) possibility that read() errors + /* + * We have to consider the (unlikely) possibility that read() errors * could result in an OA buffer reset which might reset the head and * tail state. */ @@ -557,7 +558,8 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream) hw_tail = stream->perf->ops.oa_hw_tail_read(stream); hw_tail -= gtt_offset; - /* The tail pointer increases in 64 byte increments, not in report_size + /* + * The tail pointer increases in 64 byte increments, not in report_size * steps. Also the report size may not be a power of 2. Compute * potentially partially landed report in the OA buffer */ @@ -569,8 +571,9 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream) tail = hw_tail; - /* Walk the stream backward until we find a report with report - * id and timestmap not at 0. Since the circular buffer pointers + /* + * Walk the stream backward until we find a report with report + * id and timestamp not at 0. Since the circular buffer pointers * progress by increments of 64 bytes and that reports can be up * to 256 bytes long, we can't tell whether a report has fully * landed in memory before the report id and timestamp of the @@ -3849,7 +3852,7 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf, } /* - * Asking for SSEU configuration is a priviliged operation. + * Asking for SSEU configuration is a privileged operation. */ if (props->has_sseu) privileged_op = true; @@ -4478,14 +4481,16 @@ static bool gen12_is_valid_mux_addr(struct i915_perf *perf, u32 addr) static u32 mask_reg_value(u32 reg, u32 val) { - /* HALF_SLICE_CHICKEN2 is programmed with a the + /* + * HALF_SLICE_CHICKEN2 is programmed with a the * WaDisableSTUnitPowerOptimization workaround. Make sure the value * programmed by userspace doesn't change this. */ if (REG_EQUAL(reg, HALF_SLICE_CHICKEN2)) val = val & ~_MASKED_BIT_ENABLE(GEN8_ST_PO_DISABLE); - /* WAIT_FOR_RC6_EXIT has only one bit fullfilling the function + /* + * WAIT_FOR_RC6_EXIT has only one bit fulfilling the function * indicated by its name and a bunch of selection fields used by OA * configs. */ diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 8e66d63d0c9f..0ec78c2b4f20 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -103,7 +103,7 @@ struct i915_pmu { /** * @timer_last: * - * Timestmap of the previous timer invocation. + * Timestamp of the previous timer invocation. */ ktime_t timer_last; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 765e6c0528fb..b9e2aa1c6f8a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -84,7 +84,7 @@ * Try to name registers according to the specs. If the register name changes in * the specs from platform to another, stick to the original name. * - * Try to re-use existing register macro definitions. Only add new macros for + * Try to reuse existing register macro definitions. Only add new macros for * new register offsets, or when the register contents have changed enough to * warrant a full redefinition. * @@ -492,8 +492,9 @@ #define MBUS_ABOX_BT_CREDIT_POOL1_MASK (0x1F << 0) #define MBUS_ABOX_BT_CREDIT_POOL1(x) ((x) << 0) -/* Make render/texture TLB fetches lower priorty than associated data - * fetches. This is not turned on by default +/* + * Make render/texture TLB fetches lower priority than associated data + * fetches. This is not turned on by default. */ #define MI_ARB_RENDER_TLB_LOW_PRIORITY (1 << 15) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 8f62cfa23fb7..f8c584ce3295 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -473,7 +473,7 @@ static bool __request_in_flight(const struct i915_request *signal) * to avoid tearing.] * * Note that the read of *execlists->active may race with the promotion - * of execlists->pending[] to execlists->inflight[], overwritting + * of execlists->pending[] to execlists->inflight[], overwriting * the value at *execlists->active. This is fine. The promotion implies * that we received an ACK from the HW, and so the context is not * stuck -- if we do not see ourselves in *active, the inflight status diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 0ac55b2e4223..5f7e8138ec14 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -161,7 +161,7 @@ enum { * parent-child relationship (parallel submission, multi-lrc) that * hit an error while generating requests in the execbuf IOCTL. * Indicates this request should be skipped as another request in - * submission / relationship encoutered an error. + * submission / relationship encountered an error. */ I915_FENCE_FLAG_SKIP_PARALLEL, @@ -187,7 +187,7 @@ enum { * RCU lookup of it that may race against reallocation of the struct * from the slab freelist. We intentionally do not zero the structure on * allocation so that the lookup can use the dangling pointers (and is - * cogniscent that those pointers may be wrong). Instead, everything that + * cognisant that those pointers may be wrong). Instead, everything that * needs to be initialised must be done so explicitly. * * The requests are reference counted. diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 776f8cc51b2f..61b49007ecd4 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -778,8 +778,8 @@ bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long color) * @flags: mask of PIN_* flags to use * * First we try to allocate some free space that meets the requirements for - * the VMA. Failiing that, if the flags permit, it will evict an old VMA, - * preferrably the oldest idle entry to make room for the new VMA. + * the VMA. Failing that, if the flags permit, it will evict an old VMA, + * preferably the oldest idle entry to make room for the new VMA. * * Returns: * 0 on success, negative error code otherwise. @@ -877,7 +877,7 @@ i915_vma_insert(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, * objects which need to be tightly packed into the low 32bits. * * Note that we assume that GGTT are limited to 4GiB for the - * forseeable future. See also i915_ggtt_offset(). + * foreseeable future. See also i915_ggtt_offset(). */ if (upper_32_bits(end - 1) && vma->page_sizes.sg > I915_GTT_PAGE_SIZE && @@ -1001,7 +1001,7 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset, /* * The DE ignores the PTEs for the padding tiles, the sg entry - * here is just a conenience to indicate how many padding PTEs + * here is just a convenience to indicate how many padding PTEs * to insert at this spot. */ sg_set_page(sg, NULL, left, 0); diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index f76642886569..387b26400169 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -682,7 +682,7 @@ static void i85x_init_clock_gating(struct drm_i915_private *i915) * Have FBC ignore 3D activity since we use software * render tracking, and otherwise a pure 3D workload * (even if it just renders a single frame and then does - * abosultely nothing) would not allow FBC to recompress + * absolutely nothing) would not allow FBC to recompress * until a 2D blit occurs. */ intel_uncore_write(&i915->uncore, SCPD0, diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index a5383a2bc64b..dae9dce7d1b3 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -265,7 +265,7 @@ void intel_gvt_driver_remove(struct drm_i915_private *dev_priv) } /** - * intel_gvt_resume - GVT resume routine wapper + * intel_gvt_resume - GVT resume routine wrapper * * @dev_priv: drm i915 private * * diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index ee1cd2126f97..04076316e139 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -1260,7 +1260,7 @@ static int iterate_bxt_mmio(struct intel_gvt_mmio_table_iter *iter) /** * intel_gvt_iterate_mmio_table - Iterate the GVT MMIO table - * @iter: the interator + * @iter: the iterator * * This function is called for iterating the GVT MMIO table when i915 is * taking the snapshot of the HW and GVT is building MMIO tracking table. diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 1a47ecfd3fd8..8d9f4c410546 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -375,7 +375,7 @@ void intel_runtime_pm_enable(struct intel_runtime_pm *rpm) * leave the device suspended skipping the driver's suspend handlers * if the device was already runtime suspended. This is needed due to * the difference in our runtime and system suspend sequence and - * becaue the HDA driver may require us to enable the audio power + * because the HDA driver may require us to enable the audio power * domain during system suspend. */ dev_pm_set_driver_flags(kdev, DPM_FLAG_NO_DIRECT_COMPLETE); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h index e22669d61e95..7428bd8fa67f 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.h +++ b/drivers/gpu/drm/i915/intel_runtime_pm.h @@ -31,7 +31,7 @@ struct drm_printer; * it can be changed with the standard runtime PM files from sysfs. * * The irqs_disabled variable becomes true exactly after we disable the IRQs and - * goes back to false exactly before we reenable the IRQs. We use this variable + * goes back to false exactly before we re-enable the IRQs. We use this variable * to check if someone is trying to enable/disable IRQs while they're supposed * to be disabled. This shouldn't happen and we'll print some error messages in * case it happens. diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index eed4937c3ff3..04ef628e208b 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -2477,7 +2477,7 @@ static int sanity_check_mmio_access(struct intel_uncore *uncore) /* * Sanitycheck that MMIO access to the device is working properly. If - * the CPU is unable to communcate with a PCI device, BAR reads will + * the CPU is unable to communicate with a PCI device, BAR reads will * return 0xFFFFFFFF. Let's make sure the device isn't in this state * before we start trying to access registers. * -- cgit v1.2.3-59-g8ed1b From ed868bcb4f5cecbb61c4f057aa7550650643ac3b Mon Sep 17 00:00:00 2001 From: Jesse Van Gavere Date: Mon, 6 Jan 2025 13:10:54 +0100 Subject: drm/bridge: adv7511: Switch to atomic operations Use the atomic version of enable/disable. To support bridges where bus format negotiation is needed such as TIDSS we need to implement atomic_get_input_bus_fmts, prepare the driver for this by switching the existing operations to it's atomic variants. Signed-off-by: Jesse Van Gavere Reviewed-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20250106121054.96739-1-jesseevg@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index fda66e7876b8..1a76aea6a945 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -910,14 +910,16 @@ static struct adv7511 *bridge_to_adv7511(struct drm_bridge *bridge) return container_of(bridge, struct adv7511, bridge); } -static void adv7511_bridge_enable(struct drm_bridge *bridge) +static void adv7511_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) { struct adv7511 *adv = bridge_to_adv7511(bridge); adv7511_power_on(adv); } -static void adv7511_bridge_disable(struct drm_bridge *bridge) +static void adv7511_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) { struct adv7511 *adv = bridge_to_adv7511(bridge); @@ -996,14 +998,18 @@ static void adv7511_bridge_hpd_notify(struct drm_bridge *bridge, } static const struct drm_bridge_funcs adv7511_bridge_funcs = { - .enable = adv7511_bridge_enable, - .disable = adv7511_bridge_disable, .mode_set = adv7511_bridge_mode_set, .mode_valid = adv7511_bridge_mode_valid, .attach = adv7511_bridge_attach, .detect = adv7511_bridge_detect, .edid_read = adv7511_bridge_edid_read, .hpd_notify = adv7511_bridge_hpd_notify, + + .atomic_enable = adv7511_bridge_atomic_enable, + .atomic_disable = adv7511_bridge_atomic_disable, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, }; /* ----------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 0936f0e54426177b0f0263ddf806ed5e13487db6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 22 Dec 2024 07:00:41 +0200 Subject: drm/atomic-helper: document drm_atomic_helper_check() restrictions The drm_atomic_helper_check() calls drm_atomic_helper_check_modeset() insternally. Document that corresponding restrictions also apply to the drivers that call the former function (as it's easy to miss the documentation for the latter function). Reviewed-by: Simona Vetter Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20241222-drm-dirty-modeset-v1-1-0e76a53eceb9@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/drm_atomic_helper.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 40e4e1b6c911..3034ba09c0ee 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1087,6 +1087,15 @@ EXPORT_SYMBOL(drm_atomic_helper_check_planes); * For example enable/disable of a cursor plane which have fixed zpos value * would trigger all other enabled planes to be forced to the state change. * + * IMPORTANT: + * + * As this function calls drm_atomic_helper_check_modeset() internally, its + * restrictions also apply: + * Drivers which set &drm_crtc_state.mode_changed (e.g. in their + * &drm_plane_helper_funcs.atomic_check hooks if a plane update can't be done + * without a full modeset) _must_ call drm_atomic_helper_check_modeset() + * function again after that change. + * * RETURNS: * Zero for success or -errno */ -- cgit v1.2.3-59-g8ed1b From 6ce24b3450b8e8132b74d4f0b43a48f4e370e825 Mon Sep 17 00:00:00 2001 From: Langyan Ye Date: Thu, 23 Jan 2025 19:20:55 +0800 Subject: drm/panel-edp: Add STA 116QHD024002 Add support for the STA 116QHD024002, pleace the EDID here for subsequent reference. 00 ff ff ff ff ff ff 00 4e 81 09 00 00 00 00 00 26 21 01 04 a5 1a 0e 78 02 1e b5 9a 5f 57 94 26 0f 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 8e 1c 56 a0 50 00 1e 30 28 20 55 00 00 90 10 00 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe 00 20 20 20 20 20 20 0a 20 20 20 20 20 20 00 00 00 fe 00 31 31 36 51 48 44 30 32 34 30 30 32 0a 00 3b Signed-off-by: Langyan Ye Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250123112055.1521471-1-yelangyan@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-edp.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 1721a3397dbf..25bb7e454fc9 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1808,6 +1808,12 @@ static const struct panel_delay delay_200_150_e50 = { .enable = 50, }; +static const struct panel_delay delay_200_500_e250 = { + .hpd_absent = 200, + .unprepare = 500, + .enable = 250, +}; + #define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \ { \ .ident = { \ @@ -1998,6 +2004,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('S', 'H', 'P', 0x1593, &delay_200_500_p2e100, "LQ134N1"), EDP_PANEL_ENTRY('S', 'T', 'A', 0x0004, &delay_200_500_e200, "116KHD024006"), + EDP_PANEL_ENTRY('S', 'T', 'A', 0x0009, &delay_200_500_e250, "116QHD024002"), EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"), { /* sentinal */ } -- cgit v1.2.3-59-g8ed1b From d3fedff828bb7e4a422c42caeafd5d974e24ee43 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Wed, 15 Jan 2025 14:20:29 -0800 Subject: drm/xe/oa: Set stream->pollin in xe_oa_buffer_check_unlocked We rely on stream->pollin to decide whether or not to block during poll/read calls. However, currently there are blocking read code paths which don't even set stream->pollin. The best place to consistently set stream->pollin for all code paths is therefore to set it in xe_oa_buffer_check_unlocked. Fixes: e936f885f1e9 ("drm/xe/oa/uapi: Expose OA stream fd") Signed-off-by: Ashutosh Dixit Acked-by: Rodrigo Vivi Reviewed-by: Jonathan Cavitt Reviewed-by: Umesh Nerlige Ramappa Link: https://patchwork.freedesktop.org/patch/msgid/20250115222029.3002103-1-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/xe_oa.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 6a08e6c92835..fa873f3d0a9d 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -237,7 +237,6 @@ static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) u32 tail, hw_tail, partial_report_size, available; int report_size = stream->oa_buffer.format->size; unsigned long flags; - bool pollin; spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); @@ -282,11 +281,11 @@ static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) stream->oa_buffer.tail = tail; available = xe_oa_circ_diff(stream, stream->oa_buffer.tail, stream->oa_buffer.head); - pollin = available >= stream->wait_num_reports * report_size; + stream->pollin = available >= stream->wait_num_reports * report_size; spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); - return pollin; + return stream->pollin; } static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer) @@ -294,10 +293,8 @@ static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer) struct xe_oa_stream *stream = container_of(hrtimer, typeof(*stream), poll_check_timer); - if (xe_oa_buffer_check_unlocked(stream)) { - stream->pollin = true; + if (xe_oa_buffer_check_unlocked(stream)) wake_up(&stream->poll_wq); - } hrtimer_forward_now(hrtimer, ns_to_ktime(stream->poll_period_ns)); -- cgit v1.2.3-59-g8ed1b From 8c27c4e90e3670970f51bf35051c58bf5b05ed49 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Mon, 20 Jan 2025 22:52:02 +0530 Subject: drm/i915/scaler: Add and compute scaling factors Add scaling factors to scaler_state for a particular scaler user. These factors will be used later to compute scaler prefill latency. Currently, only plane scaling factors are stored, but the same members can later be extended to store pipe scaling factors as well. --v2: - Rephrase commit message. [Ankit] - Corrects typos. [Ankit] Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250120172209.188488-2-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_display_types.h | 2 ++ drivers/gpu/drm/i915/display/skl_scaler.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 96429201b8a0..cb51b7936f93 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -711,6 +711,8 @@ struct intel_initial_plane_config { struct intel_scaler { u32 mode; bool in_use; + int hscale; + int vscale; }; struct intel_crtc_scaler_state { diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 515196e03b93..b960cba31043 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -434,6 +434,9 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat return -EINVAL; } + + scaler_state->scalers[*scaler_id].hscale = hscale; + scaler_state->scalers[*scaler_id].vscale = vscale; } drm_dbg_kms(display->drm, "[CRTC:%d:%s] attached scaler id %u.%u to %s:%d\n", -- cgit v1.2.3-59-g8ed1b From f42da9aa863eaea4e37865959ed81a60c3df72b5 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Mon, 20 Jan 2025 22:52:03 +0530 Subject: drm/i915/scaler: Use crtc_state to setup plane or pipe scaler Pass crtc_state to intel_atomic_setup_scaler, this will help to check if pch_pfit enabled or not and also will be useful to pass scaler_state with the same which will be used later to store hscale and vscale values. -- v2: - Fix typos. (Ankit) Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250120172209.188488-3-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index b960cba31043..24514cb3c605 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -319,13 +319,15 @@ static int intel_allocate_scaler(struct intel_crtc_scaler_state *scaler_state, return -1; } -static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, +static int intel_atomic_setup_scaler(struct intel_crtc_state *crtc_state, int num_scalers_need, struct intel_crtc *crtc, const char *name, int idx, struct intel_plane_state *plane_state, int *scaler_id) { struct intel_display *display = to_intel_display(crtc); + struct intel_crtc_scaler_state *scaler_state = + &crtc_state->scaler_state; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 mode; @@ -455,7 +457,7 @@ static int setup_crtc_scaler(struct intel_atomic_state *state, struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; - return intel_atomic_setup_scaler(scaler_state, + return intel_atomic_setup_scaler(crtc_state, hweight32(scaler_state->scaler_users), crtc, "CRTC", crtc->base.base.id, NULL, &scaler_state->scaler_id); @@ -490,7 +492,7 @@ static int setup_plane_scaler(struct intel_atomic_state *state, if (IS_ERR(plane_state)) return PTR_ERR(plane_state); - return intel_atomic_setup_scaler(scaler_state, + return intel_atomic_setup_scaler(crtc_state, hweight32(scaler_state->scaler_users), crtc, "PLANE", plane->base.base.id, plane_state, &plane_state->scaler_id); -- cgit v1.2.3-59-g8ed1b From cabb162f7b7d2a012c80ecc13e5e75c0d01d6dde Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Mon, 20 Jan 2025 22:52:04 +0530 Subject: drm/i915/scaler: Refactor max_scale computation Refactor max scaling factor computation into a reusable function for scalers. --v2: - Add missing comment. [Ankit] Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250120172209.188488-4-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 70 ++++++++++++++++++------------- 1 file changed, 41 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 24514cb3c605..3465f7878ed5 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -319,6 +319,44 @@ static int intel_allocate_scaler(struct intel_crtc_scaler_state *scaler_state, return -1; } +static void +calculate_max_scale(struct intel_crtc *crtc, + bool is_yuv_semiplanar, + int scaler_id, + int *max_hscale, int *max_vscale) +{ + struct intel_display *display = to_intel_display(crtc); + + /* + * FIXME: When two scalers are needed, but only one of + * them needs to downscale, we should make sure that + * the one that needs downscaling support is assigned + * as the first scaler, so we don't reject downscaling + * unnecessarily. + */ + + if (DISPLAY_VER(display) >= 14) { + /* + * On versions 14 and up, only the first + * scaler supports a vertical scaling factor + * of more than 1.0, while a horizontal + * scaling factor of 3.0 is supported. + */ + *max_hscale = 0x30000 - 1; + + if (scaler_id == 0) + *max_vscale = 0x30000 - 1; + else + *max_vscale = 0x10000; + } else if (DISPLAY_VER(display) >= 10 || !is_yuv_semiplanar) { + *max_hscale = 0x30000 - 1; + *max_vscale = 0x30000 - 1; + } else { + *max_hscale = 0x20000 - 1; + *max_vscale = 0x20000 - 1; + } +} + static int intel_atomic_setup_scaler(struct intel_crtc_state *crtc_state, int num_scalers_need, struct intel_crtc *crtc, const char *name, int idx, @@ -388,35 +426,9 @@ static int intel_atomic_setup_scaler(struct intel_crtc_state *crtc_state, const struct drm_rect *dst = &plane_state->uapi.dst; int hscale, vscale, max_vscale, max_hscale; - /* - * FIXME: When two scalers are needed, but only one of - * them needs to downscale, we should make sure that - * the one that needs downscaling support is assigned - * as the first scaler, so we don't reject downscaling - * unnecessarily. - */ - - if (DISPLAY_VER(display) >= 14) { - /* - * On versions 14 and up, only the first - * scaler supports a vertical scaling factor - * of more than 1.0, while a horizontal - * scaling factor of 3.0 is supported. - */ - max_hscale = 0x30000 - 1; - if (*scaler_id == 0) - max_vscale = 0x30000 - 1; - else - max_vscale = 0x10000; - - } else if (DISPLAY_VER(display) >= 10 || - !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { - max_hscale = 0x30000 - 1; - max_vscale = 0x30000 - 1; - } else { - max_hscale = 0x20000 - 1; - max_vscale = 0x20000 - 1; - } + calculate_max_scale(crtc, + intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier), + *scaler_id, &max_hscale, &max_vscale); /* * FIXME: We should change the if-else block above to -- cgit v1.2.3-59-g8ed1b From 9217f9aaef62236da37f6e915047352d114eff77 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Tue, 21 Jan 2025 23:28:56 +0530 Subject: drm/i915/scaler: Compute scaling factors for pipe scaler Compute scaling factors and scaler user for pipe scaler if particular scaler user is pipe scaler. --v2: - Fix typos. [Ankit] - Remove FIXME tag. [Ankit] - Should be common hscale, vscale instead of local one to avoid garbage overwritten. --v3: - Separate out max_scaling information. [Ankit] - Use max_hscale and max_vscale info instead of INT_MAX. [Ankit] --v4: - Add Suggested changes reported by Dan Carpenter. Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250121175856.447245-1-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 39 +++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 3465f7878ed5..54f9adba4ac0 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -368,6 +368,8 @@ static int intel_atomic_setup_scaler(struct intel_crtc_state *crtc_state, &crtc_state->scaler_state; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 mode; + int hscale = 0; + int vscale = 0; if (*scaler_id < 0) *scaler_id = intel_allocate_scaler(scaler_state, crtc); @@ -416,15 +418,11 @@ static int intel_atomic_setup_scaler(struct intel_crtc_state *crtc_state, mode = SKL_PS_SCALER_MODE_DYN; } - /* - * FIXME: we should also check the scaler factors for pfit, so - * this shouldn't be tied directly to planes. - */ if (plane_state && plane_state->hw.fb) { const struct drm_framebuffer *fb = plane_state->hw.fb; const struct drm_rect *src = &plane_state->uapi.src; const struct drm_rect *dst = &plane_state->uapi.dst; - int hscale, vscale, max_vscale, max_hscale; + int max_hscale, max_vscale; calculate_max_scale(crtc, intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier), @@ -448,11 +446,38 @@ static int intel_atomic_setup_scaler(struct intel_crtc_state *crtc_state, return -EINVAL; } + } + + if (crtc_state->pch_pfit.enabled) { + struct drm_rect src; + int max_hscale, max_vscale; + + drm_rect_init(&src, 0, 0, + drm_rect_width(&crtc_state->pipe_src) << 16, + drm_rect_height(&crtc_state->pipe_src) << 16); + + calculate_max_scale(crtc, 0, *scaler_id, + &max_hscale, &max_vscale); - scaler_state->scalers[*scaler_id].hscale = hscale; - scaler_state->scalers[*scaler_id].vscale = vscale; + hscale = drm_rect_calc_hscale(&src, &crtc_state->pch_pfit.dst, + 0, max_hscale); + vscale = drm_rect_calc_vscale(&src, &crtc_state->pch_pfit.dst, + 0, max_vscale); + + if (hscale < 0 || vscale < 0) { + drm_dbg_kms(display->drm, + "Scaler %d doesn't support required pipe scaling\n", + *scaler_id); + drm_rect_debug_print("src: ", &src, true); + drm_rect_debug_print("dst: ", &crtc_state->pch_pfit.dst, false); + + return -EINVAL; + } } + scaler_state->scalers[*scaler_id].hscale = hscale; + scaler_state->scalers[*scaler_id].vscale = vscale; + drm_dbg_kms(display->drm, "[CRTC:%d:%s] attached scaler id %u.%u to %s:%d\n", crtc->base.base.id, crtc->base.name, crtc->pipe, *scaler_id, name, idx); -- cgit v1.2.3-59-g8ed1b From 65599f65b4f1538f335ef4ae7612302a4183cb5e Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Mon, 20 Jan 2025 22:52:06 +0530 Subject: drm/i915/scaler: Limit pipe scaler downscaling factors for YUV420 Limit downscaling to less than 1.5 (source/destination) in the horizontal direction and 1.0 in the vertical direction, When configured for Pipe YUV 420 encoding for port output. Bspec: 50441, 7490, 69901 Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250120172209.188488-6-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 54f9adba4ac0..c8bf6fd92ce8 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -459,6 +459,16 @@ static int intel_atomic_setup_scaler(struct intel_crtc_state *crtc_state, calculate_max_scale(crtc, 0, *scaler_id, &max_hscale, &max_vscale); + /* + * When configured for Pipe YUV 420 encoding for port output, + * limit downscaling to less than 1.5 (source/destination) in + * the horizontal direction and 1.0 in the vertical direction. + */ + if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { + max_hscale = 0x18000 - 1; + max_vscale = 0x10000; + } + hscale = drm_rect_calc_hscale(&src, &crtc_state->pch_pfit.dst, 0, max_hscale); vscale = drm_rect_calc_vscale(&src, &crtc_state->pch_pfit.dst, -- cgit v1.2.3-59-g8ed1b From 9159b622ad629e6415467130dad39dd83e7b6324 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Mon, 20 Jan 2025 22:52:07 +0530 Subject: drm/i915/scaler: Check if vblank is sufficient for scaler High refresh rate panels which may have small line times and vblank sizes, Check if vblank size is sufficient for enabled scaler users. --v2: - Use hweight* family of functions for counting bits. [Jani] - Update precision handling for hscale and vscale. [Ankit] - Consider chroma downscaling factor during latency calculation. [Ankit] - Replace function name from scaler_prefill_time to scaler_prefill_latency. --v3: - hscale_k and vscale_k values are already left shifted by 16, after multiplying by 1000, those need to be right shifted to 16. [Ankit] - Replace YCBCR444 to YCBCR420. [Ankit] - Divide by 1000 * 1000 in end to get correct precision. [Ankit] - Initialise latency to 0 to avoid any garbage. --v4: - Elaborate commit message and add Bspec number. [Ankit] - Improvise latency calculation. [Ankit] - Use ceiling value for down scaling factor when less than 1 as per bspec. [Ankit] - Correct linetime calculation. [Ankit] - Consider cdclk prefill adjustment while prefill computation.[Ankit] --v5: - Add Bspec link in commit message trailer. [Ankit] - Correct hscale, vscale data type. - Use intel_crtc_compute_min_cdclk. [Ankit] --v6: - Update FIXME comment. - Use cdclk_state->logical.cdclk instead of intel_crtc_compute_min_cdclk. [Ankit] --v7: - Handle error return from cdclk_prefill_adjustment. [Ankit] - Avoid incorrect round off for linetime. [Ankit] - Correct precision. [Ankit] --v8: - Remove redundancy calculation added from previous patch. [Ankit] Bspec: 70151 Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250120172209.188488-7-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/skl_watermark.c | 53 +++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 2bc6251e93d6..a2580112b50b 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -2292,6 +2292,56 @@ static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, return 0; } +static int +cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_atomic_state *state = + to_intel_atomic_state(crtc_state->uapi.state); + const struct intel_cdclk_state *cdclk_state; + + cdclk_state = intel_atomic_get_cdclk_state(state); + if (IS_ERR(cdclk_state)) { + drm_WARN_ON(display->drm, PTR_ERR(cdclk_state)); + return 1; + } + + return min(1, DIV_ROUND_UP(crtc_state->pixel_rate, + 2 * cdclk_state->logical.cdclk)); +} + +static int +scaler_prefill_latency(const struct intel_crtc_state *crtc_state) +{ + const struct intel_crtc_scaler_state *scaler_state = + &crtc_state->scaler_state; + int num_scaler_users = hweight32(scaler_state->scaler_users); + int scaler_prefill_latency = 0; + int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal, + crtc_state->hw.adjusted_mode.clock); + + if (!num_scaler_users) + return scaler_prefill_latency; + + scaler_prefill_latency = 4 * linetime; + + if (num_scaler_users > 1) { + u64 hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16); + u64 vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16); + int chroma_downscaling_factor = + crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1; + int latency; + + latency = DIV_ROUND_UP_ULL((4 * linetime * hscale_k * vscale_k * + chroma_downscaling_factor), 1000000); + scaler_prefill_latency += latency; + } + + scaler_prefill_latency *= cdclk_prefill_adjustment(crtc_state); + + return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, scaler_prefill_latency); +} + static bool skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state, int wm0_lines, int latency) @@ -2299,9 +2349,10 @@ skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - /* FIXME missing scaler and DSC pre-fill time */ + /* FIXME missing DSC pre-fill time */ return crtc_state->framestart_delay + intel_usecs_to_scanlines(adjusted_mode, latency) + + scaler_prefill_latency(crtc_state) + wm0_lines > adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vblank_start; } -- cgit v1.2.3-59-g8ed1b From a9b14af999b058ee9371d3d8fa02245339da7302 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Mon, 20 Jan 2025 22:52:08 +0530 Subject: drm/i915/dsc: Check if vblank is sufficient for dsc prefill High refresh rate panels which may have small line times and vblank sizes, Check if vblank size is sufficient for dsc prefill latency. --v2: - Consider chroma downscaling factor in latency calculation. [Ankit] - Replace with appropriate function name. --v3: - Remove FIXME tag.[Ankit] - Replace Ycbcr444 to Ycbcr420.[Ankit] - Correct precision. [Ankit] - Use some local valiables like linetime_factor and latency to adjust precision. - Declare latency to 0 initially to avoid returning any garbage values. - Account for second scaler downscaling factor as well. [Ankit] --v4: - Improvise hscale and vscale calculation. [Ankit] - Use appropriate name for number of scaler users. [Ankit] - Update commit message and rebase. - Add linetime and cdclk prefill adjustment calculation. [Ankit] --v5: - Update bspec link in trailer. [Ankit] - Correct hscale, vscale datatype. [Ankit] - Use intel_crtc_compute_min_cdclk. [Ankit] --v6: - Use cdclk_state->logical.cdclk instead of intel_crtc_compute_min_cdclk. [Ankit] --v7: - Fix linetime calculation. [Ankit] - Reduce redandancy use of variables. [Ankit] - Fix typos. [Ankit] - Update calculation for precision. [Ankit] --v8: - Initialise variable to return garbage later. [Ankit] - Initialise few variables to use at local loop, where it is used. [Ankit] Bspec: 70151 Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250120172209.188488-8-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/skl_watermark.c | 33 +++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index a2580112b50b..45fe4aaeb450 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -2310,6 +2310,37 @@ cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state) 2 * cdclk_state->logical.cdclk)); } +static int +dsc_prefill_latency(const struct intel_crtc_state *crtc_state) +{ + const struct intel_crtc_scaler_state *scaler_state = + &crtc_state->scaler_state; + int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal, + crtc_state->hw.adjusted_mode.clock); + int num_scaler_users = hweight32(scaler_state->scaler_users); + int chroma_downscaling_factor = + crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1; + u32 dsc_prefill_latency = 0; + + if (!crtc_state->dsc.compression_enable || !num_scaler_users) + return dsc_prefill_latency; + + dsc_prefill_latency = DIV_ROUND_UP(15 * linetime * chroma_downscaling_factor, 10); + + for (int i = 0; i < num_scaler_users; i++) { + u64 hscale_k, vscale_k; + + hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].hscale, 1000) >> 16); + vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].vscale, 1000) >> 16); + dsc_prefill_latency = DIV_ROUND_UP_ULL(dsc_prefill_latency * hscale_k * vscale_k, + 1000000); + } + + dsc_prefill_latency *= cdclk_prefill_adjustment(crtc_state); + + return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, dsc_prefill_latency); +} + static int scaler_prefill_latency(const struct intel_crtc_state *crtc_state) { @@ -2349,10 +2380,10 @@ skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - /* FIXME missing DSC pre-fill time */ return crtc_state->framestart_delay + intel_usecs_to_scanlines(adjusted_mode, latency) + scaler_prefill_latency(crtc_state) + + dsc_prefill_latency(crtc_state) + wm0_lines > adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vblank_start; } -- cgit v1.2.3-59-g8ed1b From b5d97b2db08f0143202bed897874e6563c0310ab Mon Sep 17 00:00:00 2001 From: Nemesa Garg Date: Thu, 26 Dec 2024 11:36:32 +0530 Subject: drm/i915/display: Add WA_14018221282 It was observed that the first write to DKL PHY DP Mode register was not taking effect, hence rewrite this register. v2: Rename function [Mitul] v3: Rename function [Jani] v4: Add check for display ver 13 [Matt] Co-developed-by: Vandita Kulkarni Signed-off-by: Vandita Kulkarni Signed-off-by: Nemesa Garg Reviewed-by: Mika Kahola Signed-off-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/20241226060632.213790-1-nemesa.garg@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 05df8f986491..dc319f37b1be 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2120,10 +2120,21 @@ void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder) encoder->disable_clock(encoder); } +static void +tgl_dkl_phy_check_and_rewrite(struct drm_i915_private *dev_priv, + enum tc_port tc_port, u32 ln0, u32 ln1) +{ + if (ln0 != intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0))) + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0); + if (ln1 != intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1))) + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1); +} + static void icl_program_mg_dp_mode(struct intel_digital_port *dig_port, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); u32 ln0, ln1, pin_assignment; @@ -2201,6 +2212,10 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, if (DISPLAY_VER(dev_priv) >= 12) { intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0); intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1); + /* WA_14018221282 */ + if (IS_DISPLAY_VER(display, 12, 13)) + tgl_dkl_phy_check_and_rewrite(dev_priv, tc_port, ln0, ln1); + } else { intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0); intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1); -- cgit v1.2.3-59-g8ed1b From d33847a0fe83b04718ac4d7715d128001161b221 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Wed, 22 Jan 2025 11:00:23 +0530 Subject: drm/i915/cx0: Set ssc_enabled for c20 too ssc_enabled does not get set for c20 phy. We makes sure we set ssc_enabled for both c10 and c20. Bspec: 74491 Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250122053022.1544881-1-suraj.kandpal@intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20250122053022.1544881-1-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 39c98549ac4e..144d4311c0e8 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2021,21 +2021,27 @@ intel_c10pll_tables_get(struct intel_crtc_state *crtc_state, return NULL; } -static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state, +static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll; - int i; if (intel_crtc_has_dp_encoder(crtc_state)) { if (intel_panel_use_ssc(display)) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - pll_state->ssc_enabled = (intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5); } } +} + +static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(encoder); + struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll; + int i; if (pll_state->ssc_enabled) return; @@ -2058,6 +2064,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, for (i = 0; tables[i]; i++) { if (crtc_state->port_clock == tables[i]->clock) { crtc_state->dpll_hw_state.cx0pll.c10 = *tables[i]; + intel_cx0pll_update_ssc(crtc_state, encoder); intel_c10pll_update_pll(crtc_state, encoder); crtc_state->dpll_hw_state.cx0pll.use_c10 = true; @@ -2327,6 +2334,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, for (i = 0; tables[i]; i++) { if (crtc_state->port_clock == tables[i]->clock) { crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i]; + intel_cx0pll_update_ssc(crtc_state, encoder); crtc_state->dpll_hw_state.cx0pll.use_c10 = false; return 0; } -- cgit v1.2.3-59-g8ed1b From 2654d4711375ec32ffb8c83644e3af716d009b63 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 15:58:39 +0100 Subject: drm/omap/dss: Use of_property_present() to test existence of DT property of_property_read_bool() should be used only on boolean properties. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20250114145840.505459-1-krzysztof.kozlowski@linaro.org --- drivers/gpu/drm/omapdrm/dss/dss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 7b2df3185de4..319f0a1d23a7 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1236,7 +1236,7 @@ static int dss_video_pll_probe(struct dss_device *dss) if (!np) return 0; - if (of_property_read_bool(np, "syscon-pll-ctrl")) { + if (of_property_present(np, "syscon-pll-ctrl")) { dss->syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np, "syscon-pll-ctrl"); if (IS_ERR(dss->syscon_pll_ctrl)) { -- cgit v1.2.3-59-g8ed1b From 07efb761b672753a5ce911e41d2be7c171b4f18f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 15:58:40 +0100 Subject: drm/omap/dss: Use syscon_regmap_lookup_by_phandle_args Use syscon_regmap_lookup_by_phandle_args() which is a wrapper over syscon_regmap_lookup_by_phandle() combined with getting the syscon argument. Except simpler code this annotates within one line that given phandle has arguments, so grepping for code would be easier. There is also no real benefit in printing errors on missing syscon argument, because this is done just too late: runtime check on static/build-time data. Dtschema and Devicetree bindings offer the static/build-time check for this already. Reviewed-by: Tomi Valkeinen Signed-off-by: Krzysztof Kozlowski Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20250114145840.505459-2-krzysztof.kozlowski@linaro.org --- drivers/gpu/drm/omapdrm/dss/dss.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 319f0a1d23a7..692df747e2ae 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1237,20 +1237,14 @@ static int dss_video_pll_probe(struct dss_device *dss) return 0; if (of_property_present(np, "syscon-pll-ctrl")) { - dss->syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np, - "syscon-pll-ctrl"); + dss->syscon_pll_ctrl = + syscon_regmap_lookup_by_phandle_args(np, "syscon-pll-ctrl", + 1, &dss->syscon_pll_ctrl_offset); if (IS_ERR(dss->syscon_pll_ctrl)) { dev_err(&pdev->dev, "failed to get syscon-pll-ctrl regmap\n"); return PTR_ERR(dss->syscon_pll_ctrl); } - - if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1, - &dss->syscon_pll_ctrl_offset)) { - dev_err(&pdev->dev, - "failed to get syscon-pll-ctrl offset\n"); - return -EINVAL; - } } pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video"); -- cgit v1.2.3-59-g8ed1b From c905d149c506a498f8f0819c77e159d3b9e06a64 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 18 Dec 2024 02:01:24 +0000 Subject: drm/omap: Remove hdmi5_core_handle_irqs() hdmi5_core_handle_irqs() is a function that was copied from omapdss by commit f76ee892a99e ("omapfb: copy omapdss & displays for omapfb") but it wasn't used in the original anyway. Remove it. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20241218020124.278925-1-linux@treblig.org --- drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 17 ----------------- drivers/gpu/drm/omapdrm/dss/hdmi5_core.h | 1 - 2 files changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c index 21564c38234f..12ef47cd232b 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c @@ -545,23 +545,6 @@ static void hdmi_core_enable_interrupts(struct hdmi_core_data *core) REG_FLD_MOD(core->base, HDMI_CORE_IH_MUTE, 0x0, 1, 0); } -int hdmi5_core_handle_irqs(struct hdmi_core_data *core) -{ - void __iomem *base = core->base; - - REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT1, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT2, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_VP_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_I2CMPHY_STAT0, 0xff, 7, 0); - - return 0; -} - void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg) { diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h index 070cbf5fb57d..b8ed21156e8c 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h @@ -286,7 +286,6 @@ int hdmi5_core_ddc_read(void *data, u8 *buf, unsigned int block, size_t len); void hdmi5_core_ddc_uninit(struct hdmi_core_data *core); void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s); -int hdmi5_core_handle_irqs(struct hdmi_core_data *core); void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg); int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core); -- cgit v1.2.3-59-g8ed1b From 798047e63ac970f105c49c22e6d44df901c486b2 Mon Sep 17 00:00:00 2001 From: Andrew Kreimer Date: Thu, 12 Sep 2024 15:57:24 +0300 Subject: drm/tidss: Fix typos Fix typos in comments. Reported-by: Matthew Wilcox Signed-off-by: Andrew Kreimer Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20240912125735.45114-1-algonell@gmail.com --- drivers/gpu/drm/tidss/tidss_dispc_regs.h | 2 +- drivers/gpu/drm/tidss/tidss_plane.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tidss/tidss_dispc_regs.h b/drivers/gpu/drm/tidss/tidss_dispc_regs.h index 13feedfe5d6d..e88148e44937 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc_regs.h +++ b/drivers/gpu/drm/tidss/tidss_dispc_regs.h @@ -49,7 +49,7 @@ enum dispc_common_regs { /* * dispc_common_regmap should be defined as const u16 * and pointing * to a valid dss common register map for the platform, before the - * macros bellow can be used. + * macros below can be used. */ #define REG(r) (dispc_common_regmap[r ## _OFF]) diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c index 116de124bddb..719412e6c346 100644 --- a/drivers/gpu/drm/tidss/tidss_plane.c +++ b/drivers/gpu/drm/tidss/tidss_plane.c @@ -67,7 +67,7 @@ static int tidss_plane_atomic_check(struct drm_plane *plane, /* * The HW is only able to start drawing at subpixel boundary - * (the two first checks bellow). At the end of a row the HW + * (the two first checks below). At the end of a row the HW * can only jump integer number of subpixels forward to the * beginning of the next row. So we can only show picture with * integer subpixel width (the third check). However, after -- cgit v1.2.3-59-g8ed1b From 7f3b11934f9684038555fd9160e188d6893949b9 Mon Sep 17 00:00:00 2001 From: Sasha Finkelstein Date: Thu, 9 Jan 2025 22:45:46 +0100 Subject: drm/virtio: Support partial maps of GEM objects Those are useful to implement coherent cross-vm mmap. Signed-off-by: Sasha Finkelstein Reviewed-by: Dmitry Osipenko Tested-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20250109-virtgpu-gem-partial-map-v1-1-a914b48776bd@gmail.com Signed-off-by: Dmitry Osipenko [dmitry.osipenko@collabora.com: Corrected vm_size check to account vm_pgoff] --- drivers/gpu/drm/virtio/virtgpu_vram.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_vram.c b/drivers/gpu/drm/virtio/virtgpu_vram.c index 25df81c02783..5ad3b7c6f73c 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vram.c +++ b/drivers/gpu/drm/virtio/virtgpu_vram.c @@ -37,6 +37,7 @@ static int virtio_gpu_vram_mmap(struct drm_gem_object *obj, struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo); unsigned long vm_size = vma->vm_end - vma->vm_start; + unsigned long vm_end; if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE)) return -EINVAL; @@ -56,12 +57,14 @@ static int virtio_gpu_vram_mmap(struct drm_gem_object *obj, else if (vram->map_info == VIRTIO_GPU_MAP_CACHE_UNCACHED) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - /* Partial mappings of GEM buffers don't happen much in practice. */ - if (vm_size != vram->vram_node.size) + if (check_add_overflow(vma->vm_pgoff << PAGE_SHIFT, vm_size, &vm_end)) + return -EINVAL; + + if (vm_end > vram->vram_node.size) return -EINVAL; ret = io_remap_pfn_range(vma, vma->vm_start, - vram->vram_node.start >> PAGE_SHIFT, + (vram->vram_node.start >> PAGE_SHIFT) + vma->vm_pgoff, vm_size, vma->vm_page_prot); return ret; } -- cgit v1.2.3-59-g8ed1b From ce8c69ec90ca83fd4eacb246e2be699e6b439e97 Mon Sep 17 00:00:00 2001 From: Tejas Vipin Date: Wed, 22 Jan 2025 08:41:10 +0530 Subject: drm/panel: samsung-s6e88a0-ams452ef01: transition to mipi_dsi wrapped functions Changes the samsung-s6e88a0-ams452ef01 panel to use multi style functions for improved error handling. Reviewed-by: Douglas Anderson Signed-off-by: Tejas Vipin Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250122031110.286079-1-tejasvipin76@gmail.com --- .../drm/panel/panel-samsung-s6e88a0-ams452ef01.c | 91 ++++++++-------------- 1 file changed, 31 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c index d2df227abbea..57b1a899bbdc 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c @@ -39,91 +39,66 @@ static void s6e88a0_ams452ef01_reset(struct s6e88a0_ams452ef01 *ctx) static int s6e88a0_ams452ef01_on(struct s6e88a0_ams452ef01 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands - mipi_dsi_dcs_write_seq(dsi, 0xcc, 0x4c); // set Pixel Clock Divider polarity + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c); // set Pixel Clock Divider polarity - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); // set default brightness/gama - mipi_dsi_dcs_write_seq(dsi, 0xca, - 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, // V255 RR,GG,BB - 0x80, 0x80, 0x80, // V203 R,G,B - 0x80, 0x80, 0x80, // V151 R,G,B - 0x80, 0x80, 0x80, // V87 R,G,B - 0x80, 0x80, 0x80, // V51 R,G,B - 0x80, 0x80, 0x80, // V35 R,G,B - 0x80, 0x80, 0x80, // V23 R,G,B - 0x80, 0x80, 0x80, // V11 R,G,B - 0x6b, 0x68, 0x71, // V3 R,G,B - 0x00, 0x00, 0x00); // V1 R,G,B + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,// V255 RR,GG,BB + 0x80, 0x80, 0x80, // V203 R,G,B + 0x80, 0x80, 0x80, // V151 R,G,B + 0x80, 0x80, 0x80, // V87 R,G,B + 0x80, 0x80, 0x80, // V51 R,G,B + 0x80, 0x80, 0x80, // V35 R,G,B + 0x80, 0x80, 0x80, // V23 R,G,B + 0x80, 0x80, 0x80, // V11 R,G,B + 0x6b, 0x68, 0x71, // V3 R,G,B + 0x00, 0x00, 0x00); // V1 R,G,B // set default Amoled Off Ratio - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x2c, 0x0b); // set default elvss voltage - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x03); // gamma/aor update - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x2c, 0x0b); // set default elvss voltage + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03); // gamma/aor update + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } -static int s6e88a0_ams452ef01_off(struct s6e88a0_ams452ef01 *ctx) +static void s6e88a0_ams452ef01_off(struct s6e88a0_ams452ef01 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi}; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(35); - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(120); - - return 0; + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 35); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); } static int s6e88a0_ams452ef01_prepare(struct drm_panel *panel) { struct s6e88a0_ams452ef01 *ctx = to_s6e88a0_ams452ef01(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret < 0) { - dev_err(dev, "Failed to enable regulators: %d\n", ret); + if (ret < 0) return ret; - } s6e88a0_ams452ef01_reset(ctx); ret = s6e88a0_ams452ef01_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -136,12 +111,8 @@ static int s6e88a0_ams452ef01_prepare(struct drm_panel *panel) static int s6e88a0_ams452ef01_unprepare(struct drm_panel *panel) { struct s6e88a0_ams452ef01 *ctx = to_s6e88a0_ams452ef01(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = s6e88a0_ams452ef01_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + s6e88a0_ams452ef01_off(ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); -- cgit v1.2.3-59-g8ed1b From 6bbce873a9c97cb12f5455c497be279ac58e707f Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 13 Jan 2025 17:10:59 +0800 Subject: drm/dp_mst: Fix drm RAD print MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] The RAD of sideband message printed today is incorrect. For RAD stored within MST branch - If MST branch LCT is 1, it's RAD array is untouched and remained as 0. - If MST branch LCT is larger than 1, use nibble to store the up facing port number in cascaded sequence as illustrated below: u8 RAD[0] = (LCT_2_UFP << 4) | LCT_3_UFP RAD[1] = (LCT_4_UFP << 4) | LCT_5_UFP ... In drm_dp_mst_rad_to_str(), it wrongly to use BIT_MASK(4) to fetch the port number of one nibble. [How] Adjust the code by: - RAD array items are valuable only for LCT >= 1. - Use 0xF as the mask to replace BIT_MASK(4) V2: - Document how RAD is constructed (Imre) V3: - Adjust the comment for rad[] so kdoc formats it properly (Lyude) Fixes: 2f015ec6eab6 ("drm/dp_mst: Add sideband down request tracing + selftests") Cc: Imre Deak Cc: Ville Syrjälä Cc: Harry Wentland Cc: Lyude Paul Reviewed-by: Lyude Paul Signed-off-by: Wayne Lin Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20250113091100.3314533-2-Wayne.Lin@amd.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 8 ++++---- include/drm/display/drm_dp_mst_helper.h | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index f8cd094efa3c..271a00b81264 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -175,13 +175,13 @@ static int drm_dp_mst_rad_to_str(const u8 rad[8], u8 lct, char *out, size_t len) { int i; - u8 unpacked_rad[16]; + u8 unpacked_rad[16] = {}; - for (i = 0; i < lct; i++) { + for (i = 1; i < lct; i++) { if (i % 2) - unpacked_rad[i] = rad[i / 2] >> 4; + unpacked_rad[i] = rad[(i - 1) / 2] >> 4; else - unpacked_rad[i] = rad[i / 2] & BIT_MASK(4); + unpacked_rad[i] = rad[(i - 1) / 2] & 0xF; } /* TODO: Eventually add something to printk so we can format the rad diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h index a80ba457a858..6398a6b50bd1 100644 --- a/include/drm/display/drm_dp_mst_helper.h +++ b/include/drm/display/drm_dp_mst_helper.h @@ -222,6 +222,13 @@ struct drm_dp_mst_branch { */ struct list_head destroy_next; + /** + * @rad: Relative Address of the MST branch. + * For &drm_dp_mst_topology_mgr.mst_primary, it's rad[8] are all 0, + * unset and unused. For MST branches connected after mst_primary, + * in each element of rad[] the nibbles are ordered by the most + * signifcant 4 bits first and the least significant 4 bits second. + */ u8 rad[8]; u8 lct; int num_ports; -- cgit v1.2.3-59-g8ed1b From 580aa2782c5b9eb50cb3bf936bc57ec0bf7d55db Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 13 Jan 2025 17:11:00 +0800 Subject: drm/dp_mst: Add helper to get port number at specific LCT from RAD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper drm_dp_mst_get_ufp_num_at_lct_from_rad() to extract the up facing port number at specific link count from the RAD. Use the added helper in drm_dp_mst_rad_to_str() & drm_dp_get_mst_branch_device() to unify the implementation. V2: - Adjust the code format (Lyude) V3: - Adjust parameter "rad" of drm_dp_mst_get_ufp_num_at_lct_from_rad() to be constant (Kernel test robot) Cc: Imre Deak Cc: Ville Syrjälä Cc: Harry Wentland Cc: Lyude Paul Reviewed-by: Lyude Paul Signed-off-by: Wayne Lin [fixed commit message typo] Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20250113091100.3314533-3-Wayne.Lin@amd.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 29 ++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 271a00b81264..e79f4b76ec2b 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -171,18 +171,30 @@ static const char *drm_dp_mst_sideband_tx_state_str(int state) return sideband_reason_str[state]; } +static inline u8 +drm_dp_mst_get_ufp_num_at_lct_from_rad(u8 lct, const u8 *rad) +{ + int idx = (lct / 2) - 1; + int shift = (lct % 2) ? 0 : 4; + u8 ufp_num; + + /* mst_primary, it's rad is unset*/ + if (lct == 1) + return 0; + + ufp_num = (rad[idx] >> shift) & 0xf; + + return ufp_num; +} + static int drm_dp_mst_rad_to_str(const u8 rad[8], u8 lct, char *out, size_t len) { int i; u8 unpacked_rad[16] = {}; - for (i = 1; i < lct; i++) { - if (i % 2) - unpacked_rad[i] = rad[(i - 1) / 2] >> 4; - else - unpacked_rad[i] = rad[(i - 1) / 2] & 0xF; - } + for (i = 0; i < lct; i++) + unpacked_rad[i] = drm_dp_mst_get_ufp_num_at_lct_from_rad(i + 1, rad); /* TODO: Eventually add something to printk so we can format the rad * like this: 1.2.3 @@ -2544,9 +2556,8 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_ if (!mstb) goto out; - for (i = 0; i < lct - 1; i++) { - int shift = (i % 2) ? 0 : 4; - int port_num = (rad[i / 2] >> shift) & 0xf; + for (i = 1; i < lct; i++) { + int port_num = drm_dp_mst_get_ufp_num_at_lct_from_rad(i + 1, rad); list_for_each_entry(port, &mstb->ports, next) { if (port->port_num == port_num) { -- cgit v1.2.3-59-g8ed1b From 22807d30fa854bbbe26e53774c9c899c39b62a71 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:44 -0800 Subject: drm/nouveau: add a kernel doc to introduce the GSP RPC In order to explain the name clean-ups in GSP RPC routines, a kernel doc to explain the memory layout and terms is required. Add a kernel doc to introduce the GSP RPC. Cc: Danilo Krummrich Signed-off-by: Zhi Wang [ Fix bullet list indentation; add SPDX-License-Identifier. - Danilo ] Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-2-zhiw@nvidia.com --- Documentation/gpu/drivers.rst | 1 + Documentation/gpu/nouveau.rst | 29 +++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 45 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 Documentation/gpu/nouveau.rst (limited to 'drivers') diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst index 1f17ad0790d7..74fc2cbf1b6f 100644 --- a/Documentation/gpu/drivers.rst +++ b/Documentation/gpu/drivers.rst @@ -10,6 +10,7 @@ GPU Driver Documentation imagination/index mcde meson + nouveau pl111 tegra tve200 diff --git a/Documentation/gpu/nouveau.rst b/Documentation/gpu/nouveau.rst new file mode 100644 index 000000000000..0f34131ccc27 --- /dev/null +++ b/Documentation/gpu/nouveau.rst @@ -0,0 +1,29 @@ +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +=============================== + drm/nouveau NVIDIA GPU Driver +=============================== + +The drm/nouveau driver provides support for a wide range of NVIDIA GPUs, +covering GeForce, Quadro, and Tesla series, from the NV04 architecture up +to the latest Turing, Ampere, Ada families. + +NVKM: NVIDIA Kernel Manager +=========================== + +The NVKM component serves as the core abstraction layer within the nouveau +driver, responsible for managing NVIDIA GPU hardware at the kernel level. +NVKM provides a unified interface for handling various GPU architectures. + +It enables resource management, power control, memory handling, and command +submission required for the proper functioning of NVIDIA GPUs under the +nouveau driver. + +NVKM plays a critical role in abstracting hardware complexities and +providing a consistent API to upper layers of the driver stack. + +GSP Support +------------------------ + +.. kernel-doc:: drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c + :doc: GSP message queue element diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 10fe2d15b5ce..b0d623611f88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -63,6 +63,51 @@ extern struct dentry *nouveau_debugfs_root; #define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE #define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16 +/** + * DOC: GSP message queue element + * + * https://github.com/NVIDIA/open-gpu-kernel-modules/blob/535/src/nvidia/inc/kernel/gpu/gsp/message_queue_priv.h + * + * The GSP command queue and status queue are message queues for the + * communication between software and GSP. The software submits the GSP + * RPC via the GSP command queue, GSP writes the status of the submitted + * RPC in the status queue. + * + * A GSP message queue element consists of three parts: + * + * - message element header (struct r535_gsp_msg), which mostly maintains + * the metadata for queuing the element. + * + * - RPC message header (struct nvfw_gsp_rpc), which maintains the info + * of the RPC. E.g., the RPC function number. + * + * - The payload, where the RPC message stays. E.g. the params of a + * specific RPC function. Some RPC functions also have their headers + * in the payload. E.g. rm_alloc, rm_control. + * + * The memory layout of a GSP message element can be illustrated below:: + * + * +------------------------+ + * | Message Element Header | + * | (r535_gsp_msg) | + * | | + * | (r535_gsp_msg.data) | + * | | | + * |----------V-------------| + * | GSP RPC Header | + * | (nvfw_gsp_rpc) | + * | | + * | (nvfw_gsp_rpc.data) | + * | | | + * |----------V-------------| + * | Payload | + * | | + * | header(optional) | + * | params | + * +------------------------+ + * + */ + struct r535_gsp_msg { u8 auth_tag_buffer[16]; u8 aad_buffer[16]; -- cgit v1.2.3-59-g8ed1b From f98ed88eb98b84f3e12ff09ec41a36a39dc43a98 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:45 -0800 Subject: drm/nouveau: rename "repc" to "gsp_rpc_len" on the GSP message recv path The name "repc" has different meanings in different contexts. To improve the readability, it's better to refine it to a name that reflects what it actually represents. Rename "repc" to "gsp_rpc_len" in the GSP message recv path. Add an section in the doc to explain the terms. No functional change is intended. Cc: Danilo Krummrich Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-3-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 46 +++++++++++++++----------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index b0d623611f88..2f61e1a4c9ba 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -106,6 +106,9 @@ extern struct dentry *nouveau_debugfs_root; * | params | * +------------------------+ * + * Terminology: + * + * - gsp_rpc_len: size of (GSP RPC header + payload) */ struct r535_gsp_msg { @@ -135,7 +138,8 @@ r535_rpc_status_to_errno(uint32_t rpc_status) } static void * -r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 repc, u32 *prepc, int *ptime) +r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 gsp_rpc_len, u32 *prepc, + int *ptime) { struct r535_gsp_msg *mqe; u32 size, rptr = *gsp->msgq.rptr; @@ -143,7 +147,8 @@ r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 repc, u32 *prepc, int *ptime) u8 *msg; u32 len; - size = DIV_ROUND_UP(GSP_MSG_HDR_SIZE + repc, GSP_PAGE_SIZE); + size = DIV_ROUND_UP(GSP_MSG_HDR_SIZE + gsp_rpc_len, + GSP_PAGE_SIZE); if (WARN_ON(!size || size >= gsp->msgq.cnt)) return ERR_PTR(-EINVAL); @@ -169,21 +174,21 @@ r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 repc, u32 *prepc, int *ptime) return mqe->data; } - size = ALIGN(repc + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); + size = ALIGN(gsp_rpc_len + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); - msg = kvmalloc(repc, GFP_KERNEL); + msg = kvmalloc(gsp_rpc_len, GFP_KERNEL); if (!msg) return ERR_PTR(-ENOMEM); len = ((gsp->msgq.cnt - rptr) * GSP_PAGE_SIZE) - sizeof(*mqe); - len = min_t(u32, repc, len); + len = min_t(u32, gsp_rpc_len, len); memcpy(msg, mqe->data, len); - repc -= len; + gsp_rpc_len -= len; - if (repc) { + if (gsp_rpc_len) { mqe = (void *)((u8 *)gsp->shm.msgq.ptr + 0x1000 + 0 * 0x1000); - memcpy(msg + len, mqe, repc); + memcpy(msg + len, mqe, gsp_rpc_len); } rptr = (rptr + DIV_ROUND_UP(size, GSP_PAGE_SIZE)) % gsp->msgq.cnt; @@ -194,9 +199,9 @@ r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 repc, u32 *prepc, int *ptime) } static void * -r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 repc, int *ptime) +r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *ptime) { - return r535_gsp_msgq_wait(gsp, repc, NULL, ptime); + return r535_gsp_msgq_wait(gsp, gsp_rpc_len, NULL, ptime); } static int @@ -317,7 +322,7 @@ r535_gsp_msg_dump(struct nvkm_gsp *gsp, struct nvfw_gsp_rpc *msg, int lvl) } static struct nvfw_gsp_rpc * -r535_gsp_msg_recv(struct nvkm_gsp *gsp, int fn, u32 repc) +r535_gsp_msg_recv(struct nvkm_gsp *gsp, int fn, u32 gsp_rpc_len) { struct nvkm_subdev *subdev = &gsp->subdev; struct nvfw_gsp_rpc *msg; @@ -342,10 +347,11 @@ retry: r535_gsp_msg_dump(gsp, msg, NV_DBG_TRACE); if (fn && msg->function == fn) { - if (repc) { - if (msg->length < sizeof(*msg) + repc) { + if (gsp_rpc_len) { + if (msg->length < sizeof(*msg) + gsp_rpc_len) { nvkm_error(subdev, "msg len %d < %zd\n", - msg->length, sizeof(*msg) + repc); + msg->length, sizeof(*msg) + + gsp_rpc_len); r535_gsp_msg_dump(gsp, msg, NV_DBG_ERROR); r535_gsp_msg_done(gsp, msg); return ERR_PTR(-EIO); @@ -414,7 +420,8 @@ r535_gsp_rpc_poll(struct nvkm_gsp *gsp, u32 fn) } static void * -r535_gsp_rpc_send(struct nvkm_gsp *gsp, void *argv, bool wait, u32 repc) +r535_gsp_rpc_send(struct nvkm_gsp *gsp, void *argv, bool wait, + u32 gsp_rpc_len) { struct nvfw_gsp_rpc *rpc = container_of(argv, typeof(*rpc), data); struct nvfw_gsp_rpc *msg; @@ -434,7 +441,7 @@ r535_gsp_rpc_send(struct nvkm_gsp *gsp, void *argv, bool wait, u32 repc) return ERR_PTR(ret); if (wait) { - msg = r535_gsp_msg_recv(gsp, fn, repc); + msg = r535_gsp_msg_recv(gsp, fn, gsp_rpc_len); if (!IS_ERR_OR_NULL(msg)) repv = msg->data; else @@ -770,7 +777,8 @@ r535_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 argc) } static void * -r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, u32 repc) +r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, + u32 gsp_rpc_len) { struct nvfw_gsp_rpc *rpc = container_of(argv, typeof(*rpc), data); struct r535_gsp_msg *cmd = container_of((void *)rpc, typeof(*cmd), data); @@ -817,7 +825,7 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, u32 repc) /* Wait for reply. */ if (wait) { - rpc = r535_gsp_msg_recv(gsp, fn, repc); + rpc = r535_gsp_msg_recv(gsp, fn, gsp_rpc_len); if (!IS_ERR_OR_NULL(rpc)) repv = rpc->data; else @@ -826,7 +834,7 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, u32 repc) repv = NULL; } } else { - repv = r535_gsp_rpc_send(gsp, argv, wait, repc); + repv = r535_gsp_rpc_send(gsp, argv, wait, gsp_rpc_len); } done: -- cgit v1.2.3-59-g8ed1b From 2c6a79af3fe0bc5db6f1097d0f64380f557830af Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:46 -0800 Subject: drm/nouveau: rename "argv" to what it represents on the GSP message send path The name "argv" has different meanings in different functions. To improve the readability, it's better to refine it to a name that reflects what it represents. Rename "repc" to what it represents in the GSP message send path. Wrap the long container_of() into to_gsp_hdr() to make checkpatch.pl happy. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-4-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 2f61e1a4c9ba..06676c17faab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -123,6 +123,9 @@ struct r535_gsp_msg { #define GSP_MSG_HDR_SIZE offsetof(struct r535_gsp_msg, data) +#define to_gsp_hdr(p, header) \ + container_of((void *)p, typeof(*header), data) + static int r535_rpc_status_to_errno(uint32_t rpc_status) { @@ -205,9 +208,9 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *ptime) } static int -r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *argv) +r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) { - struct r535_gsp_msg *cmd = container_of(argv, typeof(*cmd), data); + struct r535_gsp_msg *cmd = to_gsp_hdr(rpc, cmd); struct r535_gsp_msg *cqe; u32 argc = cmd->checksum; u64 *ptr = (void *)cmd; @@ -420,10 +423,10 @@ r535_gsp_rpc_poll(struct nvkm_gsp *gsp, u32 fn) } static void * -r535_gsp_rpc_send(struct nvkm_gsp *gsp, void *argv, bool wait, +r535_gsp_rpc_send(struct nvkm_gsp *gsp, void *payload, bool wait, u32 gsp_rpc_len) { - struct nvfw_gsp_rpc *rpc = container_of(argv, typeof(*rpc), data); + struct nvfw_gsp_rpc *rpc = to_gsp_hdr(payload, rpc); struct nvfw_gsp_rpc *msg; u32 fn = rpc->function; void *repv = NULL; @@ -777,11 +780,11 @@ r535_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 argc) } static void * -r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, +r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, bool wait, u32 gsp_rpc_len) { - struct nvfw_gsp_rpc *rpc = container_of(argv, typeof(*rpc), data); - struct r535_gsp_msg *cmd = container_of((void *)rpc, typeof(*cmd), data); + struct nvfw_gsp_rpc *rpc = to_gsp_hdr(payload, rpc); + struct r535_gsp_msg *cmd = to_gsp_hdr(rpc, cmd); const u32 max_msg_size = (16 * 0x1000) - sizeof(struct r535_gsp_msg); const u32 max_rpc_size = max_msg_size - sizeof(*rpc); u32 rpc_size = rpc->length - sizeof(*rpc); @@ -795,11 +798,11 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, rpc->length = sizeof(*rpc) + max_rpc_size; cmd->checksum = rpc->length; - repv = r535_gsp_rpc_send(gsp, argv, false, 0); + repv = r535_gsp_rpc_send(gsp, payload, false, 0); if (IS_ERR(repv)) goto done; - argv += max_rpc_size; + payload += max_rpc_size; rpc_size -= max_rpc_size; /* Remaining chunks sent as CONTINUATION_RECORD RPCs. */ @@ -813,13 +816,13 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, goto done; } - memcpy(next, argv, size); + memcpy(next, payload, size); repv = r535_gsp_rpc_send(gsp, next, false, 0); if (IS_ERR(repv)) goto done; - argv += size; + payload += size; rpc_size -= size; } @@ -834,7 +837,7 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, repv = NULL; } } else { - repv = r535_gsp_rpc_send(gsp, argv, wait, gsp_rpc_len); + repv = r535_gsp_rpc_send(gsp, payload, wait, gsp_rpc_len); } done: -- cgit v1.2.3-59-g8ed1b From a15b5379764be947001ab81bedc3ad6ee93919f8 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:47 -0800 Subject: drm/nouveau: remove unused param repc in *rm_alloc_push() The user of *rm_alloc_push() always pass 0 in repc. Remove unused param repc since no user actually uses it. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-5-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h | 8 ++++---- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h index 5c5f4607fcc9..746e126c3ecf 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h @@ -196,7 +196,7 @@ struct nvkm_gsp { void (*rm_ctrl_done)(struct nvkm_gsp_object *, void *repv); void *(*rm_alloc_get)(struct nvkm_gsp_object *, u32 oclass, u32 argc); - void *(*rm_alloc_push)(struct nvkm_gsp_object *, void *argv, u32 repc); + void *(*rm_alloc_push)(struct nvkm_gsp_object *, void *argv); void (*rm_alloc_done)(struct nvkm_gsp_object *, void *repv); int (*rm_free)(struct nvkm_gsp_object *); @@ -353,9 +353,9 @@ nvkm_gsp_rm_alloc_get(struct nvkm_gsp_object *parent, u32 handle, u32 oclass, u3 } static inline void * -nvkm_gsp_rm_alloc_push(struct nvkm_gsp_object *object, void *argv, u32 repc) +nvkm_gsp_rm_alloc_push(struct nvkm_gsp_object *object, void *argv) { - void *repv = object->client->gsp->rm->rm_alloc_push(object, argv, repc); + void *repv = object->client->gsp->rm->rm_alloc_push(object, argv); if (IS_ERR(repv)) object->client = NULL; @@ -366,7 +366,7 @@ nvkm_gsp_rm_alloc_push(struct nvkm_gsp_object *object, void *argv, u32 repc) static inline int nvkm_gsp_rm_alloc_wr(struct nvkm_gsp_object *object, void *argv) { - void *repv = nvkm_gsp_rm_alloc_push(object, argv, 0); + void *repv = nvkm_gsp_rm_alloc_push(object, argv); if (IS_ERR(repv)) return PTR_ERR(repv); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 06676c17faab..4d15a9dea934 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -647,13 +647,13 @@ r535_gsp_rpc_rm_alloc_done(struct nvkm_gsp_object *object, void *repv) } static void * -r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *argv, u32 repc) +r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *argv) { rpc_gsp_rm_alloc_v03_00 *rpc = container_of(argv, typeof(*rpc), params); struct nvkm_gsp *gsp = object->client->gsp; - void *ret; + void *ret = NULL; - rpc = nvkm_gsp_rpc_push(gsp, rpc, true, sizeof(*rpc) + repc); + rpc = nvkm_gsp_rpc_push(gsp, rpc, true, sizeof(*rpc)); if (IS_ERR_OR_NULL(rpc)) return rpc; @@ -661,8 +661,6 @@ r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *argv, u32 repc) ret = ERR_PTR(r535_rpc_status_to_errno(rpc->status)); if (PTR_ERR(ret) != -EAGAIN && PTR_ERR(ret) != -EBUSY) nvkm_error(&gsp->subdev, "RM_ALLOC: 0x%x\n", rpc->status); - } else { - ret = repc ? rpc->params : NULL; } nvkm_gsp_rpc_done(gsp, rpc); -- cgit v1.2.3-59-g8ed1b From 0c2f211b66051f97f8e3628be3a486a5841aa1b8 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:48 -0800 Subject: drm/nouveau: rename "argv" to what it represents in *rm_{alloc, ctrl}_*() The name "argv" has different meanings in different functions. To improve the readability, it's better to refine it to a name that reflects what it represents. Rename "argv" to what it represents. Wrap the long container_of() into to_payload_header() to denote a clear meaning and make checkpatch.pl happy. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-6-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 4d15a9dea934..d3b2b545841b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -126,6 +126,9 @@ struct r535_gsp_msg { #define to_gsp_hdr(p, header) \ container_of((void *)p, typeof(*header), data) +#define to_payload_hdr(p, header) \ + container_of((void *)p, typeof(*header), params) + static int r535_rpc_status_to_errno(uint32_t rpc_status) { @@ -639,17 +642,17 @@ r535_gsp_rpc_rm_free(struct nvkm_gsp_object *object) } static void -r535_gsp_rpc_rm_alloc_done(struct nvkm_gsp_object *object, void *repv) +r535_gsp_rpc_rm_alloc_done(struct nvkm_gsp_object *object, void *params) { - rpc_gsp_rm_alloc_v03_00 *rpc = container_of(repv, typeof(*rpc), params); + rpc_gsp_rm_alloc_v03_00 *rpc = to_payload_hdr(params, rpc); nvkm_gsp_rpc_done(object->client->gsp, rpc); } static void * -r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *argv) +r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *params) { - rpc_gsp_rm_alloc_v03_00 *rpc = container_of(argv, typeof(*rpc), params); + rpc_gsp_rm_alloc_v03_00 *rpc = to_payload_hdr(params, rpc); struct nvkm_gsp *gsp = object->client->gsp; void *ret = NULL; @@ -692,25 +695,25 @@ r535_gsp_rpc_rm_alloc_get(struct nvkm_gsp_object *object, u32 oclass, u32 argc) } static void -r535_gsp_rpc_rm_ctrl_done(struct nvkm_gsp_object *object, void *repv) +r535_gsp_rpc_rm_ctrl_done(struct nvkm_gsp_object *object, void *params) { - rpc_gsp_rm_control_v03_00 *rpc = container_of(repv, typeof(*rpc), params); + rpc_gsp_rm_control_v03_00 *rpc = to_payload_hdr(params, rpc); - if (!repv) + if (!params) return; nvkm_gsp_rpc_done(object->client->gsp, rpc); } static int -r535_gsp_rpc_rm_ctrl_push(struct nvkm_gsp_object *object, void **argv, u32 repc) +r535_gsp_rpc_rm_ctrl_push(struct nvkm_gsp_object *object, void **params, u32 repc) { - rpc_gsp_rm_control_v03_00 *rpc = container_of((*argv), typeof(*rpc), params); + rpc_gsp_rm_control_v03_00 *rpc = to_payload_hdr((*params), rpc); struct nvkm_gsp *gsp = object->client->gsp; int ret = 0; rpc = nvkm_gsp_rpc_push(gsp, rpc, true, repc); if (IS_ERR_OR_NULL(rpc)) { - *argv = NULL; + *params = NULL; return PTR_ERR(rpc); } @@ -722,7 +725,7 @@ r535_gsp_rpc_rm_ctrl_push(struct nvkm_gsp_object *object, void **argv, u32 repc) } if (repc) - *argv = rpc->params; + *params = rpc->params; else nvkm_gsp_rpc_done(gsp, rpc); -- cgit v1.2.3-59-g8ed1b From bda6fe811fba6742c4ec2f3c0a962b02d7d6e87f Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:49 -0800 Subject: drm/nouveau: rename "argc" to what it represents in GSP RPC routines The name "argc" has different meanings in different functions. To improve the readability, it's better to refine it to a name that reflects what it represents. Rename "argc" to what it represents. Add terms in the decoder section to explain their meaning. No functional change is intended. Signed-off-by: Zhi Wang [ Fix indentation. - Danilo ] Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-7-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 58 +++++++++++++++----------- 1 file changed, 34 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index d3b2b545841b..0753fe07e914 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -109,6 +109,8 @@ extern struct dentry *nouveau_debugfs_root; * Terminology: * * - gsp_rpc_len: size of (GSP RPC header + payload) + * - params_size: size of params in the payload + * - payload_size: size of (header if exists + params) in the payload */ struct r535_gsp_msg { @@ -215,21 +217,21 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) { struct r535_gsp_msg *cmd = to_gsp_hdr(rpc, cmd); struct r535_gsp_msg *cqe; - u32 argc = cmd->checksum; + u32 gsp_rpc_len = cmd->checksum; u64 *ptr = (void *)cmd; u64 *end; u64 csum = 0; int free, time = 1000000; - u32 wptr, size, step; + u32 wptr, size, step, len; u32 off = 0; - argc = ALIGN(GSP_MSG_HDR_SIZE + argc, GSP_PAGE_SIZE); + len = ALIGN(GSP_MSG_HDR_SIZE + gsp_rpc_len, GSP_PAGE_SIZE); - end = (u64 *)((char *)ptr + argc); + end = (u64 *)((char *)ptr + len); cmd->pad = 0; cmd->checksum = 0; cmd->sequence = gsp->cmdq.seq++; - cmd->elem_count = DIV_ROUND_UP(argc, 0x1000); + cmd->elem_count = DIV_ROUND_UP(len, 0x1000); while (ptr < end) csum ^= *ptr++; @@ -255,7 +257,7 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) cqe = (void *)((u8 *)gsp->shm.cmdq.ptr + 0x1000 + wptr * 0x1000); step = min_t(u32, free, (gsp->cmdq.cnt - wptr)); - size = min_t(u32, argc, step * GSP_PAGE_SIZE); + size = min_t(u32, len, step * GSP_PAGE_SIZE); memcpy(cqe, (u8 *)cmd + off, size); @@ -264,8 +266,8 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) wptr = 0; off += size; - argc -= size; - } while(argc); + len -= size; + } while (len); nvkm_trace(&gsp->subdev, "cmdq: wptr %d\n", wptr); wmb(); @@ -279,17 +281,17 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) } static void * -r535_gsp_cmdq_get(struct nvkm_gsp *gsp, u32 argc) +r535_gsp_cmdq_get(struct nvkm_gsp *gsp, u32 gsp_rpc_len) { struct r535_gsp_msg *cmd; - u32 size = GSP_MSG_HDR_SIZE + argc; + u32 size = GSP_MSG_HDR_SIZE + gsp_rpc_len; size = ALIGN(size, GSP_MSG_MIN_SIZE); cmd = kvzalloc(size, GFP_KERNEL); if (!cmd) return ERR_PTR(-ENOMEM); - cmd->checksum = argc; + cmd->checksum = gsp_rpc_len; return cmd->data; } @@ -672,16 +674,22 @@ r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *params) } static void * -r535_gsp_rpc_rm_alloc_get(struct nvkm_gsp_object *object, u32 oclass, u32 argc) +r535_gsp_rpc_rm_alloc_get(struct nvkm_gsp_object *object, u32 oclass, + u32 params_size) { struct nvkm_gsp_client *client = object->client; struct nvkm_gsp *gsp = client->gsp; rpc_gsp_rm_alloc_v03_00 *rpc; - nvkm_debug(&gsp->subdev, "cli:0x%08x obj:0x%08x new obj:0x%08x cls:0x%08x argc:%d\n", - client->object.handle, object->parent->handle, object->handle, oclass, argc); + nvkm_debug(&gsp->subdev, "cli:0x%08x obj:0x%08x new obj:0x%08x\n", + client->object.handle, object->parent->handle, + object->handle); - rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_GSP_RM_ALLOC, sizeof(*rpc) + argc); + nvkm_debug(&gsp->subdev, "cls:0x%08x params_size:%d\n", oclass, + params_size); + + rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_GSP_RM_ALLOC, + sizeof(*rpc) + params_size); if (IS_ERR(rpc)) return rpc; @@ -690,7 +698,7 @@ r535_gsp_rpc_rm_alloc_get(struct nvkm_gsp_object *object, u32 oclass, u32 argc) rpc->hObject = object->handle; rpc->hClass = oclass; rpc->status = 0; - rpc->paramsSize = argc; + rpc->paramsSize = params_size; return rpc->params; } @@ -733,16 +741,17 @@ r535_gsp_rpc_rm_ctrl_push(struct nvkm_gsp_object *object, void **params, u32 rep } static void * -r535_gsp_rpc_rm_ctrl_get(struct nvkm_gsp_object *object, u32 cmd, u32 argc) +r535_gsp_rpc_rm_ctrl_get(struct nvkm_gsp_object *object, u32 cmd, u32 params_size) { struct nvkm_gsp_client *client = object->client; struct nvkm_gsp *gsp = client->gsp; rpc_gsp_rm_control_v03_00 *rpc; - nvkm_debug(&gsp->subdev, "cli:0x%08x obj:0x%08x ctrl cmd:0x%08x argc:%d\n", - client->object.handle, object->handle, cmd, argc); + nvkm_debug(&gsp->subdev, "cli:0x%08x obj:0x%08x ctrl cmd:0x%08x params_size:%d\n", + client->object.handle, object->handle, cmd, params_size); - rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_GSP_RM_CONTROL, sizeof(*rpc) + argc); + rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_GSP_RM_CONTROL, + sizeof(*rpc) + params_size); if (IS_ERR(rpc)) return rpc; @@ -750,7 +759,7 @@ r535_gsp_rpc_rm_ctrl_get(struct nvkm_gsp_object *object, u32 cmd, u32 argc) rpc->hObject = object->handle; rpc->cmd = cmd; rpc->status = 0; - rpc->paramsSize = argc; + rpc->paramsSize = params_size; return rpc->params; } @@ -763,11 +772,12 @@ r535_gsp_rpc_done(struct nvkm_gsp *gsp, void *repv) } static void * -r535_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 argc) +r535_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 payload_size) { struct nvfw_gsp_rpc *rpc; - rpc = r535_gsp_cmdq_get(gsp, ALIGN(sizeof(*rpc) + argc, sizeof(u64))); + rpc = r535_gsp_cmdq_get(gsp, ALIGN(sizeof(*rpc) + payload_size, + sizeof(u64))); if (IS_ERR(rpc)) return ERR_CAST(rpc); @@ -776,7 +786,7 @@ r535_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 argc) rpc->function = fn; rpc->rpc_result = 0xffffffff; rpc->rpc_result_private = 0xffffffff; - rpc->length = sizeof(*rpc) + argc; + rpc->length = sizeof(*rpc) + payload_size; return rpc->data; } -- cgit v1.2.3-59-g8ed1b From bbae6680cfe38b033250b483722e60ccd865976f Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:50 -0800 Subject: drm/nouveau: fix the broken marco GSP_MSG_MAX_SIZE The macro GSP_MSG_MAX_SIZE refers to another macro that doesn't exist. It represents the max GSP message element size. Fix the broken marco so it can be used to replace some magic numbers in the code. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-8-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 0753fe07e914..4e1136999678 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -61,7 +61,7 @@ extern struct dentry *nouveau_debugfs_root; #define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE -#define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16 +#define GSP_MSG_MAX_SIZE (GSP_MSG_MIN_SIZE * 16) /** * DOC: GSP message queue element -- cgit v1.2.3-59-g8ed1b From 1bb9bb50a493ad349262edbd81e3f3c583e28122 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:51 -0800 Subject: drm/nouveau: remove the magic number in r535_gsp_rpc_push() There has been a GSP_MSG_MAX_SIZE which represents the max size of a GSP message element header. Use it instead of a magic number. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-9-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 4e1136999678..78b5dc66f9e0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -796,7 +796,7 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, bool wait, { struct nvfw_gsp_rpc *rpc = to_gsp_hdr(payload, rpc); struct r535_gsp_msg *cmd = to_gsp_hdr(rpc, cmd); - const u32 max_msg_size = (16 * 0x1000) - sizeof(struct r535_gsp_msg); + const u32 max_msg_size = GSP_MSG_MAX_SIZE - sizeof(*cmd); const u32 max_rpc_size = max_msg_size - sizeof(*rpc); u32 rpc_size = rpc->length - sizeof(*rpc); void *repv; -- cgit v1.2.3-59-g8ed1b From 0268040b9c570c8fc328d3e0ea60da2e068fb76b Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:52 -0800 Subject: drm/nouveau: refine the variable names in r535_gsp_rpc_push() The variable names in r535_gsp_rpc_push() are quite confusing and some of them are not representing what they really are. Update the names and explanations in the decoder section of the kernel doc. Refine the names to align with the terms in the kernel doc. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-10-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 78b5dc66f9e0..c28bb1b4f00f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -108,6 +108,9 @@ extern struct dentry *nouveau_debugfs_root; * * Terminology: * + * - gsp_msg(msg): GSP message element (element header + GSP RPC header + + * payload) + * - gsp_rpc(rpc): GSP RPC (RPC header + payload) * - gsp_rpc_len: size of (GSP RPC header + payload) * - params_size: size of params in the payload * - payload_size: size of (header if exists + params) in the payload @@ -795,30 +798,30 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, bool wait, u32 gsp_rpc_len) { struct nvfw_gsp_rpc *rpc = to_gsp_hdr(payload, rpc); - struct r535_gsp_msg *cmd = to_gsp_hdr(rpc, cmd); - const u32 max_msg_size = GSP_MSG_MAX_SIZE - sizeof(*cmd); - const u32 max_rpc_size = max_msg_size - sizeof(*rpc); - u32 rpc_size = rpc->length - sizeof(*rpc); + struct r535_gsp_msg *msg = to_gsp_hdr(rpc, msg); + const u32 max_rpc_size = GSP_MSG_MAX_SIZE - sizeof(*msg); + const u32 max_payload_size = max_rpc_size - sizeof(*rpc); + u32 payload_size = rpc->length - sizeof(*rpc); void *repv; mutex_lock(&gsp->cmdq.mutex); - if (rpc_size > max_rpc_size) { + if (payload_size > max_payload_size) { const u32 fn = rpc->function; /* Adjust length, and send initial RPC. */ - rpc->length = sizeof(*rpc) + max_rpc_size; - cmd->checksum = rpc->length; + rpc->length = sizeof(*rpc) + max_payload_size; + msg->checksum = rpc->length; repv = r535_gsp_rpc_send(gsp, payload, false, 0); if (IS_ERR(repv)) goto done; - payload += max_rpc_size; - rpc_size -= max_rpc_size; + payload += max_payload_size; + payload_size -= max_payload_size; /* Remaining chunks sent as CONTINUATION_RECORD RPCs. */ - while (rpc_size) { - u32 size = min(rpc_size, max_rpc_size); + while (payload_size) { + u32 size = min(payload_size, max_payload_size); void *next; next = r535_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD, size); @@ -834,7 +837,7 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, bool wait, goto done; payload += size; - rpc_size -= size; + payload_size -= size; } /* Wait for reply. */ -- cgit v1.2.3-59-g8ed1b From 462445045269b2d31966b31ae5a73519d634cf16 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:53 -0800 Subject: drm/nouveau: refine the variable names in r535_gsp_msg_recv() The variable "msg" in r535_gsp_msg_recv() actually means the GSP RPC. Refine the names to align with the terms in the kernel doc. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-11-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 47 +++++++++++++------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index c28bb1b4f00f..85cd9b6ca0d8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -336,59 +336,60 @@ static struct nvfw_gsp_rpc * r535_gsp_msg_recv(struct nvkm_gsp *gsp, int fn, u32 gsp_rpc_len) { struct nvkm_subdev *subdev = &gsp->subdev; - struct nvfw_gsp_rpc *msg; + struct nvfw_gsp_rpc *rpc; int time = 4000000, i; u32 size; retry: - msg = r535_gsp_msgq_wait(gsp, sizeof(*msg), &size, &time); - if (IS_ERR_OR_NULL(msg)) - return msg; + rpc = r535_gsp_msgq_wait(gsp, sizeof(*rpc), &size, &time); + if (IS_ERR_OR_NULL(rpc)) + return rpc; - msg = r535_gsp_msgq_recv(gsp, msg->length, &time); - if (IS_ERR_OR_NULL(msg)) - return msg; + rpc = r535_gsp_msgq_recv(gsp, rpc->length, &time); + if (IS_ERR_OR_NULL(rpc)) + return rpc; - if (msg->rpc_result) { - r535_gsp_msg_dump(gsp, msg, NV_DBG_ERROR); - r535_gsp_msg_done(gsp, msg); + if (rpc->rpc_result) { + r535_gsp_msg_dump(gsp, rpc, NV_DBG_ERROR); + r535_gsp_msg_done(gsp, rpc); return ERR_PTR(-EINVAL); } - r535_gsp_msg_dump(gsp, msg, NV_DBG_TRACE); + r535_gsp_msg_dump(gsp, rpc, NV_DBG_TRACE); - if (fn && msg->function == fn) { + if (fn && rpc->function == fn) { if (gsp_rpc_len) { - if (msg->length < sizeof(*msg) + gsp_rpc_len) { - nvkm_error(subdev, "msg len %d < %zd\n", - msg->length, sizeof(*msg) + + if (rpc->length < sizeof(*rpc) + gsp_rpc_len) { + nvkm_error(subdev, "rpc len %d < %zd\n", + rpc->length, sizeof(*rpc) + gsp_rpc_len); - r535_gsp_msg_dump(gsp, msg, NV_DBG_ERROR); - r535_gsp_msg_done(gsp, msg); + r535_gsp_msg_dump(gsp, rpc, NV_DBG_ERROR); + r535_gsp_msg_done(gsp, rpc); return ERR_PTR(-EIO); } - return msg; + return rpc; } - r535_gsp_msg_done(gsp, msg); + r535_gsp_msg_done(gsp, rpc); return NULL; } for (i = 0; i < gsp->msgq.ntfy_nr; i++) { struct nvkm_gsp_msgq_ntfy *ntfy = &gsp->msgq.ntfy[i]; - if (ntfy->fn == msg->function) { + if (ntfy->fn == rpc->function) { if (ntfy->func) - ntfy->func(ntfy->priv, ntfy->fn, msg->data, msg->length - sizeof(*msg)); + ntfy->func(ntfy->priv, ntfy->fn, rpc->data, + rpc->length - sizeof(*rpc)); break; } } if (i == gsp->msgq.ntfy_nr) - r535_gsp_msg_dump(gsp, msg, NV_DBG_WARN); + r535_gsp_msg_dump(gsp, rpc, NV_DBG_WARN); - r535_gsp_msg_done(gsp, msg); + r535_gsp_msg_done(gsp, rpc); if (fn) goto retry; -- cgit v1.2.3-59-g8ed1b From 1829ee0b05177e4274cb169358f8bfea606334ea Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:54 -0800 Subject: drm/nouveau: rename the variable "cmd" to "msg" in r535_gsp_cmdq_{get, push}() Refine the name to align with the terms in the kernel doc. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-12-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 85cd9b6ca0d8..ee5b471fd787 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -218,10 +218,10 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *ptime) static int r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) { - struct r535_gsp_msg *cmd = to_gsp_hdr(rpc, cmd); + struct r535_gsp_msg *msg = to_gsp_hdr(rpc, msg); struct r535_gsp_msg *cqe; - u32 gsp_rpc_len = cmd->checksum; - u64 *ptr = (void *)cmd; + u32 gsp_rpc_len = msg->checksum; + u64 *ptr = (void *)msg; u64 *end; u64 csum = 0; int free, time = 1000000; @@ -231,15 +231,15 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) len = ALIGN(GSP_MSG_HDR_SIZE + gsp_rpc_len, GSP_PAGE_SIZE); end = (u64 *)((char *)ptr + len); - cmd->pad = 0; - cmd->checksum = 0; - cmd->sequence = gsp->cmdq.seq++; - cmd->elem_count = DIV_ROUND_UP(len, 0x1000); + msg->pad = 0; + msg->checksum = 0; + msg->sequence = gsp->cmdq.seq++; + msg->elem_count = DIV_ROUND_UP(len, 0x1000); while (ptr < end) csum ^= *ptr++; - cmd->checksum = upper_32_bits(csum) ^ lower_32_bits(csum); + msg->checksum = upper_32_bits(csum) ^ lower_32_bits(csum); wptr = *gsp->cmdq.wptr; do { @@ -254,7 +254,7 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) } while(--time); if (WARN_ON(!time)) { - kvfree(cmd); + kvfree(msg); return -ETIMEDOUT; } @@ -262,7 +262,7 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) step = min_t(u32, free, (gsp->cmdq.cnt - wptr)); size = min_t(u32, len, step * GSP_PAGE_SIZE); - memcpy(cqe, (u8 *)cmd + off, size); + memcpy(cqe, (u8 *)msg + off, size); wptr += DIV_ROUND_UP(size, 0x1000); if (wptr == gsp->cmdq.cnt) @@ -279,23 +279,23 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) nvkm_falcon_wr32(&gsp->falcon, 0xc00, 0x00000000); - kvfree(cmd); + kvfree(msg); return 0; } static void * r535_gsp_cmdq_get(struct nvkm_gsp *gsp, u32 gsp_rpc_len) { - struct r535_gsp_msg *cmd; + struct r535_gsp_msg *msg; u32 size = GSP_MSG_HDR_SIZE + gsp_rpc_len; size = ALIGN(size, GSP_MSG_MIN_SIZE); - cmd = kvzalloc(size, GFP_KERNEL); - if (!cmd) + msg = kvzalloc(size, GFP_KERNEL); + if (!msg) return ERR_PTR(-ENOMEM); - cmd->checksum = gsp_rpc_len; - return cmd->data; + msg->checksum = gsp_rpc_len; + return msg->data; } struct nvfw_gsp_rpc { -- cgit v1.2.3-59-g8ed1b From c965e3598b4ee7863d64dd13a54258753f7b447f Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:55 -0800 Subject: drm/nouveau: factor out r535_gsp_msgq_peek() To receive a GSP message queue element from the GSP status queue, the driver needs to make sure there are available elements in the queue. The previous r535_gsp_msgq_wait() consists of three functions, which is a little too complicated for a single function: - wait for an available element. - peek the message element header in the queue. - recevice the element from the queue. Factor out r535_gsp_msgq_peek() and divide the functions in r535_gsp_msgq_wait() into three functions. No functional change is intended. Cc: Danilo Krummrich Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-13-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 89 +++++++++++++++++++------- 1 file changed, 66 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index ee5b471fd787..0d582ddc2c58 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -148,20 +148,16 @@ r535_rpc_status_to_errno(uint32_t rpc_status) } } -static void * -r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 gsp_rpc_len, u32 *prepc, - int *ptime) +static int +r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *ptime) { - struct r535_gsp_msg *mqe; u32 size, rptr = *gsp->msgq.rptr; int used; - u8 *msg; - u32 len; size = DIV_ROUND_UP(GSP_MSG_HDR_SIZE + gsp_rpc_len, GSP_PAGE_SIZE); if (WARN_ON(!size || size >= gsp->msgq.cnt)) - return ERR_PTR(-EINVAL); + return -EINVAL; do { u32 wptr = *gsp->msgq.wptr; @@ -176,15 +172,69 @@ r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 gsp_rpc_len, u32 *prepc, } while (--(*ptime)); if (WARN_ON(!*ptime)) - return ERR_PTR(-ETIMEDOUT); + return -ETIMEDOUT; - mqe = (void *)((u8 *)gsp->shm.msgq.ptr + 0x1000 + rptr * 0x1000); + return used; +} - if (prepc) { - *prepc = (used * GSP_PAGE_SIZE) - sizeof(*mqe); - return mqe->data; - } +static struct r535_gsp_msg * +r535_gsp_msgq_get_entry(struct nvkm_gsp *gsp) +{ + u32 rptr = *gsp->msgq.rptr; + + /* Skip the first page, which is the message queue info */ + return (void *)((u8 *)gsp->shm.msgq.ptr + GSP_PAGE_SIZE + + rptr * GSP_PAGE_SIZE); +} +/** + * DOC: Receive a GSP message queue element + * + * Receiving a GSP message queue element from the message queue consists of + * the following steps: + * + * - Peek the element from the queue: r535_gsp_msgq_peek(). + * Peek the first page of the element to determine the total size of the + * message before allocating the proper memory. + * + * - Allocate memory and receive the message: r535_gsp_msgq_recv(). + * Once the total size of the message is determined from the GSP message + * queue element, allocate memory and copy the pages of the message + * into the allocated memory. + * + * - Free the allocated memory after processing the GSP message. + * The caller is responsible for freeing the memory allocated for the GSP + * message pages after they have been processed. + */ +static void * +r535_gsp_msgq_peek(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) +{ + struct r535_gsp_msg *mqe; + int ret; + + ret = r535_gsp_msgq_wait(gsp, gsp_rpc_len, retries); + if (ret < 0) + return ERR_PTR(ret); + + mqe = r535_gsp_msgq_get_entry(gsp); + + return mqe->data; +} + +static void * +r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) +{ + u32 rptr = *gsp->msgq.rptr; + struct r535_gsp_msg *mqe; + u32 size, len; + u8 *msg; + int ret; + + ret = r535_gsp_msgq_wait(gsp, gsp_rpc_len, retries); + if (ret < 0) + return ERR_PTR(ret); + + mqe = r535_gsp_msgq_get_entry(gsp); size = ALIGN(gsp_rpc_len + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); msg = kvmalloc(gsp_rpc_len, GFP_KERNEL); @@ -209,12 +259,6 @@ r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 gsp_rpc_len, u32 *prepc, return msg; } -static void * -r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *ptime) -{ - return r535_gsp_msgq_wait(gsp, gsp_rpc_len, NULL, ptime); -} - static int r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) { @@ -337,15 +381,14 @@ r535_gsp_msg_recv(struct nvkm_gsp *gsp, int fn, u32 gsp_rpc_len) { struct nvkm_subdev *subdev = &gsp->subdev; struct nvfw_gsp_rpc *rpc; - int time = 4000000, i; - u32 size; + int retries = 4000000, i; retry: - rpc = r535_gsp_msgq_wait(gsp, sizeof(*rpc), &size, &time); + rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), &retries); if (IS_ERR_OR_NULL(rpc)) return rpc; - rpc = r535_gsp_msgq_recv(gsp, rpc->length, &time); + rpc = r535_gsp_msgq_recv(gsp, rpc->length, &retries); if (IS_ERR_OR_NULL(rpc)) return rpc; -- cgit v1.2.3-59-g8ed1b From 3c48ecb38a736bf457233dc6869e305aee6d52f9 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:56 -0800 Subject: drm/nouveau: factor out r535_gsp_msgq_recv_one_elem() Prepare for supporting receive the large GSP RPC message. Factor out r535_gsp_msgq_recv_one_elem(). Fold its params into a data structure of params. Move the allocation of the GSP RPC message to its caller. Refine the variable names in the re-factor. No functional change is intended. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-14-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 72 +++++++++++++++++++------- 1 file changed, 52 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 0d582ddc2c58..c074679605fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -111,6 +111,7 @@ extern struct dentry *nouveau_debugfs_root; * - gsp_msg(msg): GSP message element (element header + GSP RPC header + * payload) * - gsp_rpc(rpc): GSP RPC (RPC header + payload) + * - gsp_rpc_buf: buffer for (GSP RPC header + payload) * - gsp_rpc_len: size of (GSP RPC header + payload) * - params_size: size of params in the payload * - payload_size: size of (header if exists + params) in the payload @@ -197,13 +198,16 @@ r535_gsp_msgq_get_entry(struct nvkm_gsp *gsp) * Peek the first page of the element to determine the total size of the * message before allocating the proper memory. * - * - Allocate memory and receive the message: r535_gsp_msgq_recv(). + * - Allocate memory for the message. * Once the total size of the message is determined from the GSP message - * queue element, allocate memory and copy the pages of the message - * into the allocated memory. + * queue element, the caller of r535_gsp_msgq_recv() allocates the + * required memory. * - * - Free the allocated memory after processing the GSP message. - * The caller is responsible for freeing the memory allocated for the GSP + * - Receive the message: r535_gsp_msgq_recv(). + * Copy the message into the allocated memory. Advance the read pointer. + * + * - Free the allocated memory: r535_gsp_msg_done(). + * The user is responsible for freeing the memory allocated for the GSP * message pages after they have been processed. */ static void * @@ -221,42 +225,70 @@ r535_gsp_msgq_peek(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) return mqe->data; } +struct r535_gsp_msg_info { + int *retries; + u32 gsp_rpc_len; + void *gsp_rpc_buf; +}; + static void * -r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) +r535_gsp_msgq_recv_one_elem(struct nvkm_gsp *gsp, + struct r535_gsp_msg_info *info) { + u8 *buf = info->gsp_rpc_buf; u32 rptr = *gsp->msgq.rptr; struct r535_gsp_msg *mqe; - u32 size, len; - u8 *msg; + u32 size, expected, len; int ret; - ret = r535_gsp_msgq_wait(gsp, gsp_rpc_len, retries); + expected = info->gsp_rpc_len; + + ret = r535_gsp_msgq_wait(gsp, expected, info->retries); if (ret < 0) return ERR_PTR(ret); mqe = r535_gsp_msgq_get_entry(gsp); - size = ALIGN(gsp_rpc_len + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); - - msg = kvmalloc(gsp_rpc_len, GFP_KERNEL); - if (!msg) - return ERR_PTR(-ENOMEM); + size = ALIGN(expected + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); len = ((gsp->msgq.cnt - rptr) * GSP_PAGE_SIZE) - sizeof(*mqe); - len = min_t(u32, gsp_rpc_len, len); - memcpy(msg, mqe->data, len); + len = min_t(u32, expected, len); + memcpy(buf, mqe->data, len); - gsp_rpc_len -= len; + expected -= len; - if (gsp_rpc_len) { + if (expected) { mqe = (void *)((u8 *)gsp->shm.msgq.ptr + 0x1000 + 0 * 0x1000); - memcpy(msg + len, mqe, gsp_rpc_len); + memcpy(buf + len, mqe, expected); } rptr = (rptr + DIV_ROUND_UP(size, GSP_PAGE_SIZE)) % gsp->msgq.cnt; mb(); (*gsp->msgq.rptr) = rptr; - return msg; + return buf; +} + +static void * +r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) +{ + struct r535_gsp_msg_info info = {0}; + void *buf; + + buf = kvmalloc(gsp_rpc_len, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + info.gsp_rpc_buf = buf; + info.retries = retries; + info.gsp_rpc_len = gsp_rpc_len; + + buf = r535_gsp_msgq_recv_one_elem(gsp, &info); + if (IS_ERR(buf)) { + kvfree(info.gsp_rpc_buf); + info.gsp_rpc_buf = NULL; + } + + return buf; } static int -- cgit v1.2.3-59-g8ed1b From 50f290053d79e3b1d108f181c0ba6b8e30ca94c9 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:57 -0800 Subject: drm/nouveau: support handling the return of large GSP message The max GSP message element size is 16 pages (including the headers). To send a message larger than 16 pages, nvkm should split it into multiple and send them accordingly. The first element has the expected function number, while the rest are sent with function number as NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD. GSP consumes the elements from the cmdq and always writes the result back to the msgq. The result is also formed as split elements. However, nvkm is able to split the large GSP message and send them, but totally not aware of handling the return of the large GSP message, which are the split elements in the msgq. Thus, it keeps dumping the unknown RPC messages from msgq, which is actually CONTINUATION_RECORD message, discard them unexpectedly. Thus, the caller will not be able to consume the result from GSP. Introduce the handling of the return of large GSP message on the msgq path. Slightly re-factor the low-level part of msg receiving routines. Merge the split elements back into a large element before handling it to the upper level. Thus, the upper-level of GSP RPC APIs don't need to be heavily changed. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-15-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 116 +++++++++++++++++++++---- 1 file changed, 97 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index c074679605fc..b3f8d33fdd60 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -106,6 +106,17 @@ extern struct dentry *nouveau_debugfs_root; * | params | * +------------------------+ * + * The max size of a message queue element is 16 pages (including the + * headers). When a GSP message to be sent is larger than 16 pages, the + * message should be split into multiple elements and sent accordingly. + * + * In the bunch of the split elements, the first element has the expected + * function number, while the rest of the elements are sent with the + * function number NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD. + * + * GSP consumes the elements from the cmdq and always writes the result + * back to the msgq. The result is also formed as split elements. + * * Terminology: * * - gsp_msg(msg): GSP message element (element header + GSP RPC header + @@ -127,6 +138,21 @@ struct r535_gsp_msg { u8 data[]; }; +struct nvfw_gsp_rpc { + u32 header_version; + u32 signature; + u32 length; + u32 function; + u32 rpc_result; + u32 rpc_result_private; + u32 sequence; + union { + u32 spare; + u32 cpuRmGfid; + }; + u8 data[]; +}; + #define GSP_MSG_HDR_SIZE offsetof(struct r535_gsp_msg, data) #define to_gsp_hdr(p, header) \ @@ -205,6 +231,11 @@ r535_gsp_msgq_get_entry(struct nvkm_gsp *gsp) * * - Receive the message: r535_gsp_msgq_recv(). * Copy the message into the allocated memory. Advance the read pointer. + * If the message is a large GSP message, r535_gsp_msgq_recv() calls + * r535_gsp_msgq_recv_one_elem() repeatedly to receive continuation parts + * until the complete message is received. + * r535_gsp_msgq_recv() assembles the payloads of cotinuation parts into + * the return of the large GSP message. * * - Free the allocated memory: r535_gsp_msg_done(). * The user is responsible for freeing the memory allocated for the GSP @@ -229,8 +260,12 @@ struct r535_gsp_msg_info { int *retries; u32 gsp_rpc_len; void *gsp_rpc_buf; + bool continuation; }; +static void +r535_gsp_msg_dump(struct nvkm_gsp *gsp, struct nvfw_gsp_rpc *msg, int lvl); + static void * r535_gsp_msgq_recv_one_elem(struct nvkm_gsp *gsp, struct r535_gsp_msg_info *info) @@ -248,11 +283,28 @@ r535_gsp_msgq_recv_one_elem(struct nvkm_gsp *gsp, return ERR_PTR(ret); mqe = r535_gsp_msgq_get_entry(gsp); + + if (info->continuation) { + struct nvfw_gsp_rpc *rpc = (struct nvfw_gsp_rpc *)mqe->data; + + if (rpc->function != NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD) { + nvkm_error(&gsp->subdev, + "Not a continuation of a large RPC\n"); + r535_gsp_msg_dump(gsp, rpc, NV_DBG_ERROR); + return ERR_PTR(-EIO); + } + } + size = ALIGN(expected + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); len = ((gsp->msgq.cnt - rptr) * GSP_PAGE_SIZE) - sizeof(*mqe); len = min_t(u32, expected, len); - memcpy(buf, mqe->data, len); + + if (info->continuation) + memcpy(buf, mqe->data + sizeof(struct nvfw_gsp_rpc), + len - sizeof(struct nvfw_gsp_rpc)); + else + memcpy(buf, mqe->data, len); expected -= len; @@ -271,16 +323,26 @@ r535_gsp_msgq_recv_one_elem(struct nvkm_gsp *gsp, static void * r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) { + struct r535_gsp_msg *mqe; + const u32 max_rpc_size = GSP_MSG_MAX_SIZE - sizeof(*mqe); + struct nvfw_gsp_rpc *rpc; struct r535_gsp_msg_info info = {0}; + u32 expected = gsp_rpc_len; void *buf; - buf = kvmalloc(gsp_rpc_len, GFP_KERNEL); + mqe = r535_gsp_msgq_get_entry(gsp); + rpc = (struct nvfw_gsp_rpc *)mqe->data; + + if (WARN_ON(rpc->length > max_rpc_size)) + return NULL; + + buf = kvmalloc(max_t(u32, rpc->length, expected), GFP_KERNEL); if (!buf) return ERR_PTR(-ENOMEM); info.gsp_rpc_buf = buf; info.retries = retries; - info.gsp_rpc_len = gsp_rpc_len; + info.gsp_rpc_len = rpc->length; buf = r535_gsp_msgq_recv_one_elem(gsp, &info); if (IS_ERR(buf)) { @@ -288,6 +350,37 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) info.gsp_rpc_buf = NULL; } + if (expected <= max_rpc_size) + return buf; + + info.gsp_rpc_buf += info.gsp_rpc_len; + expected -= info.gsp_rpc_len; + + while (expected) { + u32 size; + + rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), info.retries); + if (IS_ERR_OR_NULL(rpc)) { + kfree(buf); + return rpc; + } + + info.gsp_rpc_len = rpc->length; + info.continuation = true; + + rpc = r535_gsp_msgq_recv_one_elem(gsp, &info); + if (IS_ERR_OR_NULL(rpc)) { + kfree(buf); + return rpc; + } + + size = info.gsp_rpc_len - sizeof(*rpc); + expected -= size; + info.gsp_rpc_buf += size; + } + + rpc = buf; + rpc->length = gsp_rpc_len; return buf; } @@ -374,21 +467,6 @@ r535_gsp_cmdq_get(struct nvkm_gsp *gsp, u32 gsp_rpc_len) return msg->data; } -struct nvfw_gsp_rpc { - u32 header_version; - u32 signature; - u32 length; - u32 function; - u32 rpc_result; - u32 rpc_result_private; - u32 sequence; - union { - u32 spare; - u32 cpuRmGfid; - }; - u8 data[]; -}; - static void r535_gsp_msg_done(struct nvkm_gsp *gsp, struct nvfw_gsp_rpc *msg) { @@ -420,7 +498,7 @@ retry: if (IS_ERR_OR_NULL(rpc)) return rpc; - rpc = r535_gsp_msgq_recv(gsp, rpc->length, &retries); + rpc = r535_gsp_msgq_recv(gsp, gsp_rpc_len, &retries); if (IS_ERR_OR_NULL(rpc)) return rpc; -- cgit v1.2.3-59-g8ed1b From 24079ed2aad6567f643df0e31b631184578de4e7 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Fri, 24 Jan 2025 10:29:58 -0800 Subject: drm/nouveau: consume the return of large GSP message As the GSP message recv path is able to handle the return of large GSP message, consume the return of large GSP message in the sending path. Signed-off-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-16-zhiw@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 32 +++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index b3f8d33fdd60..2075cad63805 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -512,10 +512,9 @@ retry: if (fn && rpc->function == fn) { if (gsp_rpc_len) { - if (rpc->length < sizeof(*rpc) + gsp_rpc_len) { - nvkm_error(subdev, "rpc len %d < %zd\n", - rpc->length, sizeof(*rpc) + - gsp_rpc_len); + if (rpc->length < gsp_rpc_len) { + nvkm_error(subdev, "rpc len %d < %d\n", + rpc->length, gsp_rpc_len); r535_gsp_msg_dump(gsp, rpc, NV_DBG_ERROR); r535_gsp_msg_done(gsp, rpc); return ERR_PTR(-EIO); @@ -961,6 +960,7 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, bool wait, mutex_lock(&gsp->cmdq.mutex); if (payload_size > max_payload_size) { const u32 fn = rpc->function; + u32 remain_payload_size = payload_size; /* Adjust length, and send initial RPC. */ rpc->length = sizeof(*rpc) + max_payload_size; @@ -971,11 +971,12 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, bool wait, goto done; payload += max_payload_size; - payload_size -= max_payload_size; + remain_payload_size -= max_payload_size; /* Remaining chunks sent as CONTINUATION_RECORD RPCs. */ - while (payload_size) { - u32 size = min(payload_size, max_payload_size); + while (remain_payload_size) { + u32 size = min(remain_payload_size, + max_payload_size); void *next; next = r535_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD, size); @@ -991,18 +992,21 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, bool wait, goto done; payload += size; - payload_size -= size; + remain_payload_size -= size; } /* Wait for reply. */ - if (wait) { - rpc = r535_gsp_msg_recv(gsp, fn, gsp_rpc_len); - if (!IS_ERR_OR_NULL(rpc)) + rpc = r535_gsp_msg_recv(gsp, fn, payload_size + + sizeof(*rpc)); + if (!IS_ERR_OR_NULL(rpc)) { + if (wait) { repv = rpc->data; - else - repv = rpc; + } else { + nvkm_gsp_rpc_done(gsp, rpc); + repv = NULL; + } } else { - repv = NULL; + repv = wait ? rpc : NULL; } } else { repv = r535_gsp_rpc_send(gsp, payload, wait, gsp_rpc_len); -- cgit v1.2.3-59-g8ed1b From c852646f12d4cd5b4f19eeec2976c5d98c0382f8 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 8 Jan 2025 18:03:54 +0100 Subject: drm: bridge: adv7511: fill stream capabilities Set no_i2s_capture and no_spdif_capture flags in hdmi_codec_pdata structure to report that the ADV7511 HDMI bridge does not support i2s or spdif audio capture. Signed-off-by: Olivier Moysan Reviewed-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20250108170356.413063-2-olivier.moysan@foss.st.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c index 51fb9a574b4e..ae853f6485b6 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c @@ -235,7 +235,9 @@ static const struct hdmi_codec_pdata codec_data = { .ops = &adv7511_codec_ops, .max_i2s_channels = 2, .i2s = 1, + .no_i2s_capture = 1, .spdif = 1, + .no_spdif_capture = 1, }; int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511) -- cgit v1.2.3-59-g8ed1b From 7c3127e4814c304c7d5a2fa796a42e75a9b8606f Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 8 Jan 2025 18:03:56 +0100 Subject: drm: bridge: adv7511: remove s32 format from i2s capabilities The ADV7511 chip allows 24 bits samples max in I2S mode, excepted for direct AES3 mode (SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE format). However the HDMI codec exposes S32_LE format as supported. Adapt ADV7511 HDMI I2S format list to expose formats actually supported. Signed-off-by: Olivier Moysan Reviewed-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20250108170356.413063-4-olivier.moysan@foss.st.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c index ae853f6485b6..36a7b6f085f9 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c @@ -233,6 +233,9 @@ static const struct hdmi_codec_ops adv7511_codec_ops = { static const struct hdmi_codec_pdata codec_data = { .ops = &adv7511_codec_ops, + .i2s_formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE), .max_i2s_channels = 2, .i2s = 1, .no_i2s_capture = 1, -- cgit v1.2.3-59-g8ed1b From 011c1e246a1d01c9d4b3b183e469bdb87b1f7bb8 Mon Sep 17 00:00:00 2001 From: Vinay Belgaumkar Date: Thu, 23 Jan 2025 21:04:06 -0800 Subject: drm/xe/pmu: Enable PMU interface Basic PMU enabling patch. Setup the basic framework for adding events. Based on previous versions by Bommu Krishnaiah, Aravind Iddamsetty and Riana Tauro, using i915 and rapl as reference implementations. Reviewed-by: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar Link: https://patchwork.freedesktop.org/patch/msgid/20250124050411.2189060-1-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/Makefile | 2 + drivers/gpu/drm/xe/xe_device.c | 3 + drivers/gpu/drm/xe/xe_device_types.h | 4 + drivers/gpu/drm/xe/xe_pmu.c | 289 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pmu.h | 18 +++ drivers/gpu/drm/xe/xe_pmu_types.h | 35 +++++ 6 files changed, 351 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_pmu.c create mode 100644 drivers/gpu/drm/xe/xe_pmu.h create mode 100644 drivers/gpu/drm/xe/xe_pmu_types.h (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 2e50a697f549..9122e4318773 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -122,6 +122,8 @@ xe-$(CONFIG_HMM_MIRROR) += xe_hmm.o # graphics hardware monitoring (HWMON) support xe-$(CONFIG_HWMON) += xe_hwmon.o +xe-$(CONFIG_PERF_EVENTS) += xe_pmu.o + # graphics virtualization (SR-IOV) support xe-y += \ xe_gt_sriov_vf.o \ diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index af9b2bb62dee..90597a7ad0b0 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -49,6 +49,7 @@ #include "xe_pat.h" #include "xe_pcode.h" #include "xe_pm.h" +#include "xe_pmu.h" #include "xe_query.h" #include "xe_sriov.h" #include "xe_tile.h" @@ -872,6 +873,8 @@ int xe_device_probe(struct xe_device *xe) xe_oa_register(xe); + xe_pmu_register(&xe->pmu); + xe_debugfs_register(xe); xe_hwmon_register(xe); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 16ebb2859877..58e79e19deaa 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -18,6 +18,7 @@ #include "xe_memirq_types.h" #include "xe_oa_types.h" #include "xe_platform_types.h" +#include "xe_pmu_types.h" #include "xe_pt_types.h" #include "xe_sriov_types.h" #include "xe_step_types.h" @@ -514,6 +515,9 @@ struct xe_device { int mode; } wedged; + /** @pmu: performance monitoring unit */ + struct xe_pmu pmu; + #ifdef TEST_VM_OPS_ERROR /** * @vm_inject_error_position: inject errors at different places in VM diff --git a/drivers/gpu/drm/xe/xe_pmu.c b/drivers/gpu/drm/xe/xe_pmu.c new file mode 100644 index 000000000000..b3da3863928a --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pmu.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2025 Intel Corporation + */ + +#include +#include + +#include "xe_device.h" +#include "xe_pmu.h" + +/** + * DOC: Xe PMU (Performance Monitoring Unit) + * + * Expose events/counters like GT-C6 residency and GT frequency to user land via + * the perf interface. Events are per device. The GT can be selected with an + * extra config sub-field (bits 60-63). + * + * All events are listed in sysfs: + * + * $ ls -ld /sys/bus/event_source/devices/xe_* + * $ ls /sys/bus/event_source/devices/xe_0000_00_02.0/events/ + * $ ls /sys/bus/event_source/devices/xe_0000_00_02.0/format/ + * + * The format directory has info regarding the configs that can be used. + * The standard perf tool can be used to grep for a certain event as well. + * Example: + * + * $ perf list | grep gt-c6 + * + * To sample a specific event for a GT at regular intervals: + * + * $ perf stat -e -I + */ + +#define XE_PMU_EVENT_GT_MASK GENMASK_ULL(63, 60) +#define XE_PMU_EVENT_ID_MASK GENMASK_ULL(11, 0) + +static unsigned int config_to_event_id(u64 config) +{ + return FIELD_GET(XE_PMU_EVENT_ID_MASK, config); +} + +static unsigned int config_to_gt_id(u64 config) +{ + return FIELD_GET(XE_PMU_EVENT_GT_MASK, config); +} + +static struct xe_gt *event_to_gt(struct perf_event *event) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + u64 gt = config_to_gt_id(event->attr.config); + + return xe_device_get_gt(xe, gt); +} + +static bool event_supported(struct xe_pmu *pmu, unsigned int gt, + unsigned int id) +{ + if (gt >= XE_MAX_GT_PER_TILE) + return false; + + return false; +} + +static void xe_pmu_event_destroy(struct perf_event *event) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + + drm_WARN_ON(&xe->drm, event->parent); + drm_dev_put(&xe->drm); +} + +static int xe_pmu_event_init(struct perf_event *event) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + struct xe_pmu *pmu = &xe->pmu; + unsigned int id, gt; + + if (!pmu->registered) + return -ENODEV; + + if (event->attr.type != event->pmu->type) + return -ENOENT; + + /* unsupported modes and filters */ + if (event->attr.sample_period) /* no sampling */ + return -EINVAL; + + if (event->cpu < 0) + return -EINVAL; + + gt = config_to_gt_id(event->attr.config); + id = config_to_event_id(event->attr.config); + if (!event_supported(pmu, gt, id)) + return -ENOENT; + + if (has_branch_stack(event)) + return -EOPNOTSUPP; + + if (!event->parent) { + drm_dev_get(&xe->drm); + event->destroy = xe_pmu_event_destroy; + } + + return 0; +} + +static u64 __xe_pmu_event_read(struct perf_event *event) +{ + struct xe_gt *gt = event_to_gt(event); + u64 val = 0; + + if (!gt) + return 0; + + return val; +} + +static void xe_pmu_event_read(struct perf_event *event) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + struct hw_perf_event *hwc = &event->hw; + struct xe_pmu *pmu = &xe->pmu; + u64 prev, new; + + if (!pmu->registered) { + event->hw.state = PERF_HES_STOPPED; + return; + } + + prev = local64_read(&hwc->prev_count); + do { + new = __xe_pmu_event_read(event); + } while (!local64_try_cmpxchg(&hwc->prev_count, &prev, new)); + + local64_add(new - prev, &event->count); +} + +static void xe_pmu_enable(struct perf_event *event) +{ + /* + * Store the current counter value so we can report the correct delta + * for all listeners. Even when the event was already enabled and has + * an existing non-zero value. + */ + local64_set(&event->hw.prev_count, __xe_pmu_event_read(event)); +} + +static void xe_pmu_event_start(struct perf_event *event, int flags) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + struct xe_pmu *pmu = &xe->pmu; + + if (!pmu->registered) + return; + + xe_pmu_enable(event); + event->hw.state = 0; +} + +static void xe_pmu_event_stop(struct perf_event *event, int flags) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + struct xe_pmu *pmu = &xe->pmu; + + if (pmu->registered) + if (flags & PERF_EF_UPDATE) + xe_pmu_event_read(event); + + event->hw.state = PERF_HES_STOPPED; +} + +static int xe_pmu_event_add(struct perf_event *event, int flags) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + struct xe_pmu *pmu = &xe->pmu; + + if (!pmu->registered) + return -ENODEV; + + if (flags & PERF_EF_START) + xe_pmu_event_start(event, flags); + + return 0; +} + +static void xe_pmu_event_del(struct perf_event *event, int flags) +{ + xe_pmu_event_stop(event, PERF_EF_UPDATE); +} + +PMU_FORMAT_ATTR(gt, "config:60-63"); +PMU_FORMAT_ATTR(event, "config:0-11"); + +static struct attribute *pmu_format_attrs[] = { + &format_attr_event.attr, + &format_attr_gt.attr, + NULL, +}; + +static const struct attribute_group pmu_format_attr_group = { + .name = "format", + .attrs = pmu_format_attrs, +}; + +static struct attribute *pmu_event_attrs[] = { + /* No events yet */ + NULL, +}; + +static const struct attribute_group pmu_events_attr_group = { + .name = "events", + .attrs = pmu_event_attrs, +}; + +/** + * xe_pmu_unregister() - Remove/cleanup PMU registration + * @arg: Ptr to pmu + */ +static void xe_pmu_unregister(void *arg) +{ + struct xe_pmu *pmu = arg; + struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); + + if (!pmu->registered) + return; + + pmu->registered = false; + + perf_pmu_unregister(&pmu->base); + kfree(pmu->name); +} + +/** + * xe_pmu_register() - Define basic PMU properties for Xe and add event callbacks. + * @pmu: the PMU object + * + * Returns 0 on success and an appropriate error code otherwise + */ +int xe_pmu_register(struct xe_pmu *pmu) +{ + struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); + static const struct attribute_group *attr_groups[] = { + &pmu_format_attr_group, + &pmu_events_attr_group, + NULL + }; + int ret = -ENOMEM; + char *name; + + if (IS_SRIOV_VF(xe)) + return 0; + + name = kasprintf(GFP_KERNEL, "xe_%s", + dev_name(xe->drm.dev)); + if (!name) + goto err; + + /* tools/perf reserves colons as special. */ + strreplace(name, ':', '_'); + + pmu->name = name; + pmu->base.attr_groups = attr_groups; + pmu->base.scope = PERF_PMU_SCOPE_SYS_WIDE; + pmu->base.module = THIS_MODULE; + pmu->base.task_ctx_nr = perf_invalid_context; + pmu->base.event_init = xe_pmu_event_init; + pmu->base.add = xe_pmu_event_add; + pmu->base.del = xe_pmu_event_del; + pmu->base.start = xe_pmu_event_start; + pmu->base.stop = xe_pmu_event_stop; + pmu->base.read = xe_pmu_event_read; + + ret = perf_pmu_register(&pmu->base, pmu->name, -1); + if (ret) + goto err_name; + + pmu->registered = true; + + return devm_add_action_or_reset(xe->drm.dev, xe_pmu_unregister, pmu); + +err_name: + kfree(name); +err: + drm_err(&xe->drm, "Failed to register PMU (ret=%d)!\n", ret); + + return ret; +} diff --git a/drivers/gpu/drm/xe/xe_pmu.h b/drivers/gpu/drm/xe/xe_pmu.h new file mode 100644 index 000000000000..60c37126f87e --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pmu.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2025 Intel Corporation + */ + +#ifndef _XE_PMU_H_ +#define _XE_PMU_H_ + +#include "xe_pmu_types.h" + +#if IS_ENABLED(CONFIG_PERF_EVENTS) +int xe_pmu_register(struct xe_pmu *pmu); +#else +static inline int xe_pmu_register(struct xe_pmu *pmu) { return 0; } +#endif + +#endif + diff --git a/drivers/gpu/drm/xe/xe_pmu_types.h b/drivers/gpu/drm/xe/xe_pmu_types.h new file mode 100644 index 000000000000..0e8faae6bc1b --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pmu_types.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2025 Intel Corporation + */ + +#ifndef _XE_PMU_TYPES_H_ +#define _XE_PMU_TYPES_H_ + +#include +#include + +#define XE_PMU_MAX_GT 2 + +/** + * struct xe_pmu - PMU related data per Xe device + * + * Stores per device PMU info that includes event/perf attributes and sampling + * counters across all GTs for this device. + */ +struct xe_pmu { + /** + * @base: PMU base. + */ + struct pmu base; + /** + * @registered: PMU is registered and not in the unregistering process. + */ + bool registered; + /** + * @name: Name as registered with perf core. + */ + const char *name; +}; + +#endif -- cgit v1.2.3-59-g8ed1b From 257a10c18e18cbcec7b9621820c11a5c9ec613bd Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 23 Jan 2025 21:04:07 -0800 Subject: drm/xe/pmu: Assert max gt XE_PMU_MAX_GT needs to be used due to a circular dependency, but we should make sure it doesn't go out of sync with XE_PMU_MAX_GT. Add a compile check for that. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250124050411.2189060-2-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_pmu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pmu.c b/drivers/gpu/drm/xe/xe_pmu.c index b3da3863928a..df93ba96bdc1 100644 --- a/drivers/gpu/drm/xe/xe_pmu.c +++ b/drivers/gpu/drm/xe/xe_pmu.c @@ -249,6 +249,8 @@ int xe_pmu_register(struct xe_pmu *pmu) int ret = -ENOMEM; char *name; + BUILD_BUG_ON(XE_MAX_GT_PER_TILE != XE_PMU_MAX_GT); + if (IS_SRIOV_VF(xe)) return 0; -- cgit v1.2.3-59-g8ed1b From ef7ce3938621e47c6aa2d517eab6f1d484ad365b Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 23 Jan 2025 21:04:08 -0800 Subject: drm/xe/pmu: Extract xe_pmu_event_update() Like other pmu drivers, keep the update separate from the read so it can be called from other methods (like stop()) without side effects. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250124050411.2189060-3-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_pmu.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pmu.c b/drivers/gpu/drm/xe/xe_pmu.c index df93ba96bdc1..33598272db6a 100644 --- a/drivers/gpu/drm/xe/xe_pmu.c +++ b/drivers/gpu/drm/xe/xe_pmu.c @@ -117,18 +117,11 @@ static u64 __xe_pmu_event_read(struct perf_event *event) return val; } -static void xe_pmu_event_read(struct perf_event *event) +static void xe_pmu_event_update(struct perf_event *event) { - struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); struct hw_perf_event *hwc = &event->hw; - struct xe_pmu *pmu = &xe->pmu; u64 prev, new; - if (!pmu->registered) { - event->hw.state = PERF_HES_STOPPED; - return; - } - prev = local64_read(&hwc->prev_count); do { new = __xe_pmu_event_read(event); @@ -137,6 +130,19 @@ static void xe_pmu_event_read(struct perf_event *event) local64_add(new - prev, &event->count); } +static void xe_pmu_event_read(struct perf_event *event) +{ + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); + struct xe_pmu *pmu = &xe->pmu; + + if (!pmu->registered) { + event->hw.state = PERF_HES_STOPPED; + return; + } + + xe_pmu_event_update(event); +} + static void xe_pmu_enable(struct perf_event *event) { /* @@ -166,7 +172,7 @@ static void xe_pmu_event_stop(struct perf_event *event, int flags) if (pmu->registered) if (flags & PERF_EF_UPDATE) - xe_pmu_event_read(event); + xe_pmu_event_update(event); event->hw.state = PERF_HES_STOPPED; } -- cgit v1.2.3-59-g8ed1b From 4ee64041bcca5289623c287336bfd94a42f42104 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 23 Jan 2025 21:04:09 -0800 Subject: drm/xe/pmu: Get/put runtime pm on event init When the event is created, make sure runtime pm is taken and later put: in order to read an event counter the GPU needs to remain accessible and doing a get/put during perf's read is not possible it's holding a raw_spinlock. Suggested-by: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250124050411.2189060-4-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_pmu.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pmu.c b/drivers/gpu/drm/xe/xe_pmu.c index 33598272db6a..6678340d6195 100644 --- a/drivers/gpu/drm/xe/xe_pmu.c +++ b/drivers/gpu/drm/xe/xe_pmu.c @@ -7,6 +7,7 @@ #include #include "xe_device.h" +#include "xe_pm.h" #include "xe_pmu.h" /** @@ -68,6 +69,7 @@ static void xe_pmu_event_destroy(struct perf_event *event) struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); drm_WARN_ON(&xe->drm, event->parent); + xe_pm_runtime_put(xe); drm_dev_put(&xe->drm); } @@ -100,6 +102,7 @@ static int xe_pmu_event_init(struct perf_event *event) if (!event->parent) { drm_dev_get(&xe->drm); + xe_pm_runtime_get(xe); event->destroy = xe_pmu_event_destroy; } -- cgit v1.2.3-59-g8ed1b From 6ea5bf169ad4b5b2da1e7753031b446c22edecf3 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 23 Jan 2025 21:04:10 -0800 Subject: drm/xe/pmu: Add attribute skeleton Add the generic support for defining new attributes. This only adds the macros and common infra for the event counters, but no counters yet. This is going to be added as follow up changes. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250124050411.2189060-5-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_pmu.c | 69 ++++++++++++++++++++++++++++++++++++--- drivers/gpu/drm/xe/xe_pmu_types.h | 4 +++ 2 files changed, 69 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pmu.c b/drivers/gpu/drm/xe/xe_pmu.c index 6678340d6195..6e19e08dd617 100644 --- a/drivers/gpu/drm/xe/xe_pmu.c +++ b/drivers/gpu/drm/xe/xe_pmu.c @@ -61,7 +61,8 @@ static bool event_supported(struct xe_pmu *pmu, unsigned int gt, if (gt >= XE_MAX_GT_PER_TILE) return false; - return false; + return id < sizeof(pmu->supported_events) * BITS_PER_BYTE && + pmu->supported_events & BIT_ULL(id); } static void xe_pmu_event_destroy(struct perf_event *event) @@ -213,16 +214,73 @@ static const struct attribute_group pmu_format_attr_group = { .attrs = pmu_format_attrs, }; -static struct attribute *pmu_event_attrs[] = { - /* No events yet */ +__maybe_unused static ssize_t event_attr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct perf_pmu_events_attr *pmu_attr = + container_of(attr, struct perf_pmu_events_attr, attr); + + return sprintf(buf, "event=%#04llx\n", pmu_attr->id); +} + +#define XE_EVENT_ATTR(name_, v_, id_) \ + PMU_EVENT_ATTR(name_, pmu_event_ ## v_, id_, event_attr_show) + +#define XE_EVENT_ATTR_UNIT(name_, v_, unit_) \ + PMU_EVENT_ATTR_STRING(name_.unit, pmu_event_unit_ ## v_, unit_) + +#define XE_EVENT_ATTR_GROUP(v_, id_, ...) \ + static struct attribute *pmu_attr_ ##v_[] = { \ + __VA_ARGS__, \ + NULL \ + }; \ + static umode_t is_visible_##v_(struct kobject *kobj, \ + struct attribute *attr, int idx) \ + { \ + struct perf_pmu_events_attr *pmu_attr; \ + struct xe_pmu *pmu; \ + \ + pmu_attr = container_of(attr, typeof(*pmu_attr), attr.attr); \ + pmu = container_of(dev_get_drvdata(kobj_to_dev(kobj)), \ + typeof(*pmu), base); \ + \ + return event_supported(pmu, 0, id_) ? attr->mode : 0; \ + } \ + static const struct attribute_group pmu_group_ ##v_ = { \ + .name = "events", \ + .attrs = pmu_attr_ ## v_, \ + .is_visible = is_visible_ ## v_, \ + } + +#define XE_EVENT_ATTR_SIMPLE(name_, v_, id_, unit_) \ + XE_EVENT_ATTR(name_, v_, id_) \ + XE_EVENT_ATTR_UNIT(name_, v_, unit_) \ + XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr, \ + &pmu_event_unit_ ##v_.attr.attr) + +#define XE_EVENT_ATTR_NOUNIT(name_, v_, id_) \ + XE_EVENT_ATTR(name_, v_, id_) \ + XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr) + +static struct attribute *pmu_empty_event_attrs[] = { + /* Empty - all events are added as groups with .attr_update() */ NULL, }; static const struct attribute_group pmu_events_attr_group = { .name = "events", - .attrs = pmu_event_attrs, + .attrs = pmu_empty_event_attrs, }; +static const struct attribute_group *pmu_events_attr_update[] = { + /* No events yet */ + NULL, +}; + +static void set_supported_events(struct xe_pmu *pmu) +{ +} + /** * xe_pmu_unregister() - Remove/cleanup PMU registration * @arg: Ptr to pmu @@ -273,6 +331,7 @@ int xe_pmu_register(struct xe_pmu *pmu) pmu->name = name; pmu->base.attr_groups = attr_groups; + pmu->base.attr_update = pmu_events_attr_update; pmu->base.scope = PERF_PMU_SCOPE_SYS_WIDE; pmu->base.module = THIS_MODULE; pmu->base.task_ctx_nr = perf_invalid_context; @@ -283,6 +342,8 @@ int xe_pmu_register(struct xe_pmu *pmu) pmu->base.stop = xe_pmu_event_stop; pmu->base.read = xe_pmu_event_read; + set_supported_events(pmu); + ret = perf_pmu_register(&pmu->base, pmu->name, -1); if (ret) goto err_name; diff --git a/drivers/gpu/drm/xe/xe_pmu_types.h b/drivers/gpu/drm/xe/xe_pmu_types.h index 0e8faae6bc1b..f5ba4d56622c 100644 --- a/drivers/gpu/drm/xe/xe_pmu_types.h +++ b/drivers/gpu/drm/xe/xe_pmu_types.h @@ -30,6 +30,10 @@ struct xe_pmu { * @name: Name as registered with perf core. */ const char *name; + /** + * @supported_events: Bitmap of supported events, indexed by event id + */ + u64 supported_events; }; #endif -- cgit v1.2.3-59-g8ed1b From 897286f2948cefe5f9d37fc3148fc19d0c7b160c Mon Sep 17 00:00:00 2001 From: Vinay Belgaumkar Date: Thu, 23 Jan 2025 21:04:11 -0800 Subject: drm/xe/pmu: Add GT C6 events Provide a PMU interface for GT C6 residency counters. The interface is similar to the one available for i915, but gt is passed in the config when creating the event. Sample usage and output: $ perf list | grep gt-c6 xe_0000_00_02.0/gt-c6-residency/ [Kernel PMU event] $ tail /sys/bus/event_source/devices/xe_0000_00_02.0/events/gt-c6-residency* ==> /sys/bus/event_source/devices/xe_0000_00_02.0/events/gt-c6-residency <== event=0x01 ==> /sys/bus/event_source/devices/xe_0000_00_02.0/events/gt-c6-residency.unit <== ms $ perf stat -e xe_0000_00_02.0/gt-c6-residency,gt=0/ -I1000 # time counts unit events 1.001196056 1,001 ms xe_0000_00_02.0/gt-c6-residency,gt=0/ 2.005216219 1,003 ms xe_0000_00_02.0/gt-c6-residency,gt=0/ Reviewed-by: Rodrigo Vivi Reviewed-by: Riana Tauro Signed-off-by: Vinay Belgaumkar Link: https://patchwork.freedesktop.org/patch/msgid/20250124050411.2189060-6-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_pmu.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pmu.c b/drivers/gpu/drm/xe/xe_pmu.c index 6e19e08dd617..3910a82328ee 100644 --- a/drivers/gpu/drm/xe/xe_pmu.c +++ b/drivers/gpu/drm/xe/xe_pmu.c @@ -7,6 +7,7 @@ #include #include "xe_device.h" +#include "xe_gt_idle.h" #include "xe_pm.h" #include "xe_pmu.h" @@ -47,6 +48,8 @@ static unsigned int config_to_gt_id(u64 config) return FIELD_GET(XE_PMU_EVENT_GT_MASK, config); } +#define XE_PMU_EVENT_GT_C6_RESIDENCY 0x01 + static struct xe_gt *event_to_gt(struct perf_event *event) { struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); @@ -113,12 +116,16 @@ static int xe_pmu_event_init(struct perf_event *event) static u64 __xe_pmu_event_read(struct perf_event *event) { struct xe_gt *gt = event_to_gt(event); - u64 val = 0; if (!gt) return 0; - return val; + switch (config_to_event_id(event->attr.config)) { + case XE_PMU_EVENT_GT_C6_RESIDENCY: + return xe_gt_idle_residency_msec(>->gtidle); + } + + return 0; } static void xe_pmu_event_update(struct perf_event *event) @@ -214,8 +221,8 @@ static const struct attribute_group pmu_format_attr_group = { .attrs = pmu_format_attrs, }; -__maybe_unused static ssize_t event_attr_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t event_attr_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct perf_pmu_events_attr *pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); @@ -262,6 +269,8 @@ __maybe_unused static ssize_t event_attr_show(struct device *dev, XE_EVENT_ATTR(name_, v_, id_) \ XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr) +XE_EVENT_ATTR_SIMPLE(gt-c6-residency, gt_c6_residency, XE_PMU_EVENT_GT_C6_RESIDENCY, "ms"); + static struct attribute *pmu_empty_event_attrs[] = { /* Empty - all events are added as groups with .attr_update() */ NULL, @@ -273,12 +282,16 @@ static const struct attribute_group pmu_events_attr_group = { }; static const struct attribute_group *pmu_events_attr_update[] = { - /* No events yet */ + &pmu_group_gt_c6_residency, NULL, }; static void set_supported_events(struct xe_pmu *pmu) { + struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); + + if (!xe->info.skip_guc_pc) + pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_C6_RESIDENCY); } /** -- cgit v1.2.3-59-g8ed1b From f14d81b7102bdbf062f90b3910e986850f5f86c2 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Fri, 24 Jan 2025 14:38:14 -0300 Subject: drm/i915/cmtg: Disable the CMTG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CMTG is a timing generator that runs in parallel with transcoders timing generators and can be used as a reference for synchronization. We have observed that we are inheriting from GOP a display configuration with the CMTG enabled. Because our driver doesn't currently implement any CMTG sequences, the CMTG ends up still enabled after our driver takes over. We need to make sure that the CMTG is not enabled if we are not going to use it. For that, let's add a partial implementation in our driver that only cares about disabling the CMTG if it was found enabled during initial hardware readout. In the future, we can also implement sequences for using the CMTG if that becomes a needed feature. For now, we only deal with cases when it is possible to disable the CMTG without requiring a modeset. For earlier display versions, we simply skip if we find the CMTG enabled and we can't disable it without a proper modeset. In the future, we need to properly handle that case. v2: - DG2 does not have the CMTG. Update HAS_CMTG() accordingly. - Update logic to force disabling of CMTG only for initial commit. v3: - Add missing changes for v2 that were staged but not committed. v4: - Avoid if/else duplication in intel_cmtg_dump_state() by using "n/a" for CMTG B enabled/disabled string for platforms without it. (Jani) - Prefer intel_cmtg_readout_hw_state() over intel_cmtg_readout_state(). (Jani) - Use display struct instead of i915 as first parameter for TRANS_DDI_FUNC_CTL2(). (Jani) - Fewer continuation lines in variable declaration/initialization for better readability. (Jani) - Coding style improvements. (Jani) - Use drm_dbg_kms() instead of drm_info() for logging the disabling of the CMTG. - Make struct intel_cmtg_state entirely private to intel_cmtg.c. v5: - Do the disable sequence as part of the sanitization step after hardware readout instead of initial modeset commit. (Jani) - Adapt to commit 15133582465f ("drm/i915/display: convert global state to struct intel_display") by using a display struct instead of i915 as argument for intel_atomic_global_obj_init(). v6: - Do not track CMTG state as a global state. (Ville) - Simplify the driver logic by only disabling the CMTG only on cases when a modeset is not required. (Ville) v7: - Remove the call to drm_WARN_ON() when checking intel_cmtg_disable_requires_modeset() and use a FIXME in the comment instead. - Remove the !HAS_CMTG() guard from intel_cmtg_get_config(), which is static and its caller is already protected by that same condition. - Also take the opportunity to put some Bspec references in the commit trailers section. v8: - Use HAS_TRANSCODER() instead of intel_crtc_for_pipe(). (Ville) - Ensure transcoder power well is enabled before reading TRANS_DDI_FUNC_CTL2. (Ville) Bspec: 68915, 49262 Cc: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20250124173956.46534-1-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_cmtg.c | 190 +++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_cmtg.h | 13 ++ drivers/gpu/drm/i915/display/intel_cmtg_regs.h | 21 +++ .../gpu/drm/i915/display/intel_display_device.h | 1 + drivers/gpu/drm/i915/display/intel_modeset_setup.c | 3 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/xe/Makefile | 1 + 8 files changed, 231 insertions(+) create mode 100644 drivers/gpu/drm/i915/display/intel_cmtg.c create mode 100644 drivers/gpu/drm/i915/display/intel_cmtg.h create mode 100644 drivers/gpu/drm/i915/display/intel_cmtg_regs.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 4caa8e30bc98..ed05b131ed3a 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -231,6 +231,7 @@ i915-y += \ display/intel_bo.o \ display/intel_bw.o \ display/intel_cdclk.o \ + display/intel_cmtg.o \ display/intel_color.o \ display/intel_combo_phy.o \ display/intel_connector.o \ diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c b/drivers/gpu/drm/i915/display/intel_cmtg.c new file mode 100644 index 000000000000..6b6fb82009f5 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2025 Intel Corporation + */ + +#include +#include + +#include +#include + +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_crtc.h" +#include "intel_cmtg.h" +#include "intel_cmtg_regs.h" +#include "intel_de.h" +#include "intel_display_device.h" +#include "intel_display_power.h" + +/** + * DOC: Common Primary Timing Generator (CMTG) + * + * The CMTG is a timing generator that runs in parallel to transcoders timing + * generators (TG) to provide a synchronization mechanism where CMTG acts as + * primary and transcoders TGs act as secondary to the CMTG. The CMTG outputs + * its TG start and frame sync signals to the transcoders that are configured + * as secondary, which use those signals to synchronize their own timing with + * the CMTG's. + * + * The CMTG can be used only with eDP or MIPI command mode and supports the + * following use cases: + * + * - Dual eDP: The CMTG can be used to keep two eDP TGs in sync when on a + * dual eDP configuration (with or without PSR/PSR2 enabled). + * + * - Single eDP as secondary: It is also possible to use a single eDP + * configuration with the transcoder TG as secondary to the CMTG. That would + * allow a flow that would not require a modeset on the existing eDP when a + * new eDP is added for a dual eDP configuration with CMTG. + * + * - DC6v: In DC6v, the transcoder might be off but the CMTG keeps running to + * maintain frame timings. When exiting DC6v, the transcoder TG then is + * synced back the CMTG. + * + * Currently, the driver does not use the CMTG, but we need to make sure that + * we disable it in case we inherit a display configuration with it enabled. + */ + +/* + * We describe here only the minimum data required to allow us to properly + * disable the CMTG if necessary. + */ +struct intel_cmtg_config { + bool cmtg_a_enable; + /* + * Xe2_LPD adds a second CMTG that can be used for dual eDP async mode. + */ + bool cmtg_b_enable; + bool trans_a_secondary; + bool trans_b_secondary; +}; + +static bool intel_cmtg_has_cmtg_b(struct intel_display *display) +{ + return DISPLAY_VER(display) >= 20; +} + +static bool intel_cmtg_has_clock_sel(struct intel_display *display) +{ + return DISPLAY_VER(display) >= 14; +} + +static void intel_cmtg_dump_config(struct intel_display *display, + struct intel_cmtg_config *cmtg_config) +{ + drm_dbg_kms(display->drm, + "CMTG readout: CMTG A: %s, CMTG B: %s, Transcoder A secondary: %s, Transcoder B secondary: %s\n", + str_enabled_disabled(cmtg_config->cmtg_a_enable), + intel_cmtg_has_cmtg_b(display) ? str_enabled_disabled(cmtg_config->cmtg_b_enable) : "n/a", + str_yes_no(cmtg_config->trans_a_secondary), + str_yes_no(cmtg_config->trans_b_secondary)); +} + +static bool intel_cmtg_transcoder_is_secondary(struct intel_display *display, + enum transcoder trans) +{ + struct drm_i915_private *i915 = to_i915(display->drm); + enum intel_display_power_domain power_domain; + intel_wakeref_t wakeref; + u32 val = 0; + + if (!HAS_TRANSCODER(display, trans)) + return false; + + power_domain = POWER_DOMAIN_TRANSCODER(trans); + + with_intel_display_power_if_enabled(i915, power_domain, wakeref) + val = intel_de_read(display, TRANS_DDI_FUNC_CTL2(display, trans)); + + return val & CMTG_SECONDARY_MODE; +} + +static void intel_cmtg_get_config(struct intel_display *display, + struct intel_cmtg_config *cmtg_config) +{ + u32 val; + + val = intel_de_read(display, TRANS_CMTG_CTL_A); + cmtg_config->cmtg_a_enable = val & CMTG_ENABLE; + + if (intel_cmtg_has_cmtg_b(display)) { + val = intel_de_read(display, TRANS_CMTG_CTL_B); + cmtg_config->cmtg_b_enable = val & CMTG_ENABLE; + } + + cmtg_config->trans_a_secondary = intel_cmtg_transcoder_is_secondary(display, TRANSCODER_A); + cmtg_config->trans_b_secondary = intel_cmtg_transcoder_is_secondary(display, TRANSCODER_B); +} + +static bool intel_cmtg_disable_requires_modeset(struct intel_display *display, + struct intel_cmtg_config *cmtg_config) +{ + if (DISPLAY_VER(display) >= 20) + return false; + + return cmtg_config->trans_a_secondary || cmtg_config->trans_b_secondary; +} + +static void intel_cmtg_disable(struct intel_display *display, + struct intel_cmtg_config *cmtg_config) +{ + u32 clk_sel_clr = 0; + u32 clk_sel_set = 0; + + if (cmtg_config->trans_a_secondary) + intel_de_rmw(display, TRANS_DDI_FUNC_CTL2(display, TRANSCODER_A), + CMTG_SECONDARY_MODE, 0); + + if (cmtg_config->trans_b_secondary) + intel_de_rmw(display, TRANS_DDI_FUNC_CTL2(display, TRANSCODER_B), + CMTG_SECONDARY_MODE, 0); + + if (cmtg_config->cmtg_a_enable) { + drm_dbg_kms(display->drm, "Disabling CMTG A\n"); + intel_de_rmw(display, TRANS_CMTG_CTL_A, CMTG_ENABLE, 0); + clk_sel_clr |= CMTG_CLK_SEL_A_MASK; + clk_sel_set |= CMTG_CLK_SEL_A_DISABLED; + } + + if (cmtg_config->cmtg_b_enable) { + drm_dbg_kms(display->drm, "Disabling CMTG B\n"); + intel_de_rmw(display, TRANS_CMTG_CTL_B, CMTG_ENABLE, 0); + clk_sel_clr |= CMTG_CLK_SEL_B_MASK; + clk_sel_set |= CMTG_CLK_SEL_B_DISABLED; + } + + if (intel_cmtg_has_clock_sel(display) && clk_sel_clr) + intel_de_rmw(display, CMTG_CLK_SEL, clk_sel_clr, clk_sel_set); +} + +/* + * Read out CMTG configuration and, on platforms that allow disabling it without + * a modeset, do it. + * + * This function must be called before any port PLL is disabled in the general + * sanitization process, because we need whatever port PLL that is providing the + * clock for CMTG to be on before accessing CMTG registers. + */ +void intel_cmtg_sanitize(struct intel_display *display) +{ + struct intel_cmtg_config cmtg_config = {}; + + if (!HAS_CMTG(display)) + return; + + intel_cmtg_get_config(display, &cmtg_config); + intel_cmtg_dump_config(display, &cmtg_config); + + /* + * FIXME: The driver is not prepared to handle cases where a modeset is + * required for disabling the CMTG: we need a proper way of tracking + * CMTG state and do the right syncronization with respect to triggering + * the modeset as part of the disable sequence. + */ + if (intel_cmtg_disable_requires_modeset(display, &cmtg_config)) + return; + + intel_cmtg_disable(display, &cmtg_config); +} diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.h b/drivers/gpu/drm/i915/display/intel_cmtg.h new file mode 100644 index 000000000000..ba62199adaa2 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_cmtg.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2025 Intel Corporation + */ + +#ifndef __INTEL_CMTG_H__ +#define __INTEL_CMTG_H__ + +struct intel_display; + +void intel_cmtg_sanitize(struct intel_display *display); + +#endif /* __INTEL_CMTG_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_cmtg_regs.h b/drivers/gpu/drm/i915/display/intel_cmtg_regs.h new file mode 100644 index 000000000000..668e41d65e86 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_cmtg_regs.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2025 Intel Corporation + */ + +#ifndef __INTEL_CMTG_REGS_H__ +#define __INTEL_CMTG_REGS_H__ + +#include "i915_reg_defs.h" + +#define CMTG_CLK_SEL _MMIO(0x46160) +#define CMTG_CLK_SEL_A_MASK REG_GENMASK(31, 29) +#define CMTG_CLK_SEL_A_DISABLED REG_FIELD_PREP(CMTG_CLK_SEL_A_MASK, 0) +#define CMTG_CLK_SEL_B_MASK REG_GENMASK(15, 13) +#define CMTG_CLK_SEL_B_DISABLED REG_FIELD_PREP(CMTG_CLK_SEL_B_MASK, 0) + +#define TRANS_CMTG_CTL_A _MMIO(0x6fa88) +#define TRANS_CMTG_CTL_B _MMIO(0x6fb88) +#define CMTG_ENABLE REG_BIT(31) + +#endif /* __INTEL_CMTG_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index a7b5ce69cf17..fc33791f02b9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -146,6 +146,7 @@ struct intel_display_platforms { #define HAS_BIGJOINER(__display) (DISPLAY_VER(__display) >= 11 && HAS_DSC(__display)) #define HAS_CDCLK_CRAWL(__display) (DISPLAY_INFO(__display)->has_cdclk_crawl) #define HAS_CDCLK_SQUASH(__display) (DISPLAY_INFO(__display)->has_cdclk_squash) +#define HAS_CMTG(__display) (!(__display)->platform.dg2 && DISPLAY_VER(__display) >= 13) #define HAS_CUR_FBC(__display) (!HAS_GMCH(__display) && IS_DISPLAY_VER(__display, 7, 13)) #define HAS_D12_PLANE_MINIMIZATION(__display) ((__display)->platform.rocketlake || (__display)->platform.alderlake_s) #define HAS_DBUF_OVERLAP_DETECTION(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dbuf_overlap_detection) diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 9a2bea19f17b..10cdfdad82e4 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -15,6 +15,7 @@ #include "i9xx_wm.h" #include "intel_atomic.h" #include "intel_bw.h" +#include "intel_cmtg.h" #include "intel_color.h" #include "intel_crtc.h" #include "intel_crtc_state_dump.h" @@ -978,6 +979,8 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915, intel_pch_sanitize(i915); + intel_cmtg_sanitize(display); + /* * intel_sanitize_plane_mapping() may need to do vblank * waits, so we need vblank interrupts restored beforehand. diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b9e2aa1c6f8a..03da51b03fb9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3566,6 +3566,7 @@ enum skl_power_gate { #define _TRANS_DDI_FUNC_CTL2_DSI1 0x6bc04 #define TRANS_DDI_FUNC_CTL2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL2_A) #define PORT_SYNC_MODE_ENABLE REG_BIT(4) +#define CMTG_SECONDARY_MODE REG_BIT(3) #define PORT_SYNC_MODE_MASTER_SELECT_MASK REG_GENMASK(2, 0) #define PORT_SYNC_MODE_MASTER_SELECT(x) REG_FIELD_PREP(PORT_SYNC_MODE_MASTER_SELECT_MASK, (x)) diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index f639c9d75023..3a243c4ea79b 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -199,6 +199,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_bios.o \ i915-display/intel_bw.o \ i915-display/intel_cdclk.o \ + i915-display/intel_cmtg.o \ i915-display/intel_color.o \ i915-display/intel_combo_phy.o \ i915-display/intel_connector.o \ -- cgit v1.2.3-59-g8ed1b From 14b66746088098f43db1e8732ff8902ddbdd4de0 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 24 Jan 2025 19:52:47 +0100 Subject: drm/xe/pf: Use GuC Buffer Cache during policy provisioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Start using GuC buffer cache for the SRIOV policy configuration actions. This is a required step before we could declare SRIOV PF as being a reclaim safe. Signed-off-by: Michal Wajdeczko Cc: Thomas Hellström Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20250124185247.676-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c | 50 ++++++++++++++---------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index c00fb354705f..4445f660e6d1 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -10,6 +10,7 @@ #include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_policy.h" #include "xe_gt_sriov_printk.h" +#include "xe_guc_buf.h" #include "xe_guc_ct.h" #include "xe_guc_klv_helpers.h" #include "xe_pm.h" @@ -34,48 +35,28 @@ static int guc_action_update_vgt_policy(struct xe_guc *guc, u64 addr, u32 size) * Return: number of KLVs that were successfully parsed and saved, * negative error code on failure. */ -static int pf_send_policy_klvs(struct xe_gt *gt, const u32 *klvs, u32 num_dwords) +static int pf_send_policy_klvs(struct xe_gt *gt, struct xe_guc_buf buf, u32 num_dwords) { - const u32 bytes = num_dwords * sizeof(u32); - struct xe_tile *tile = gt_to_tile(gt); - struct xe_device *xe = tile_to_xe(tile); struct xe_guc *guc = >->uc.guc; - struct xe_bo *bo; - int ret; - - bo = xe_bo_create_pin_map(xe, tile, NULL, - ALIGN(bytes, PAGE_SIZE), - ttm_bo_type_kernel, - XE_BO_FLAG_VRAM_IF_DGFX(tile) | - XE_BO_FLAG_GGTT); - if (IS_ERR(bo)) - return PTR_ERR(bo); - - xe_map_memcpy_to(xe, &bo->vmap, 0, klvs, bytes); - ret = guc_action_update_vgt_policy(guc, xe_bo_ggtt_addr(bo), num_dwords); - - xe_bo_unpin_map_no_vm(bo); - - return ret; + return guc_action_update_vgt_policy(guc, xe_guc_buf_flush(buf), num_dwords); } /* * Return: 0 on success, -ENOKEY if some KLVs were not updated, -EPROTO if reply was malformed, * negative error code on failure. */ -static int pf_push_policy_klvs(struct xe_gt *gt, u32 num_klvs, - const u32 *klvs, u32 num_dwords) +static int pf_push_policy_buf_klvs(struct xe_gt *gt, u32 num_klvs, + struct xe_guc_buf buf, u32 num_dwords) { int ret; - xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); - - ret = pf_send_policy_klvs(gt, klvs, num_dwords); + ret = pf_send_policy_klvs(gt, buf, num_dwords); if (ret != num_klvs) { int err = ret < 0 ? ret : ret < num_klvs ? -ENOKEY : -EPROTO; struct drm_printer p = xe_gt_info_printer(gt); + void *klvs = xe_guc_buf_cpu_ptr(buf); xe_gt_sriov_notice(gt, "Failed to push %u policy KLV%s (%pe)\n", num_klvs, str_plural(num_klvs), ERR_PTR(err)); @@ -86,6 +67,23 @@ static int pf_push_policy_klvs(struct xe_gt *gt, u32 num_klvs, return 0; } +/* + * Return: 0 on success, -ENOBUFS if there is no free buffer for the indirect data, + * negative error code on failure. + */ +static int pf_push_policy_klvs(struct xe_gt *gt, u32 num_klvs, + const u32 *klvs, u32 num_dwords) +{ + CLASS(xe_guc_buf_from_data, buf)(>->uc.guc.buf, klvs, num_dwords * sizeof(u32)); + + xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); + + if (!xe_guc_buf_is_valid(buf)) + return -ENOBUFS; + + return pf_push_policy_buf_klvs(gt, num_klvs, buf, num_dwords); +} + static int pf_push_policy_u32(struct xe_gt *gt, u16 key, u32 value) { u32 klv[] = { -- cgit v1.2.3-59-g8ed1b From 93b69c0482cf2a18d078fb1edefb4b84130838af Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Sat, 25 Jan 2025 00:38:46 +0000 Subject: drm/i915: Remove unused live_context_for_engine The last use of live_context_for_engine() was removed in 2021 by commit 99919be74aa3 ("drm/i915/gem: Zap the i915_gem_object_blt code") Remove it. Reviewed-by: Rodrigo Vivi Signed-off-by: Dr. David Alan Gilbert Link: https://patchwork.freedesktop.org/patch/msgid/20250125003846.228514-1-linux@treblig.org Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/selftests/mock_context.c | 38 ----------------------- drivers/gpu/drm/i915/gem/selftests/mock_context.h | 3 -- 2 files changed, 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c index 2b0327cc47c2..fd8babb513e5 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c @@ -107,44 +107,6 @@ err_ctx: return ERR_PTR(err); } -struct i915_gem_context * -live_context_for_engine(struct intel_engine_cs *engine, struct file *file) -{ - struct i915_gem_engines *engines; - struct i915_gem_context *ctx; - struct intel_sseu null_sseu = {}; - struct intel_context *ce; - - engines = alloc_engines(1); - if (!engines) - return ERR_PTR(-ENOMEM); - - ctx = live_context(engine->i915, file); - if (IS_ERR(ctx)) { - __free_engines(engines, 0); - return ctx; - } - - ce = intel_context_create(engine); - if (IS_ERR(ce)) { - __free_engines(engines, 0); - return ERR_CAST(ce); - } - - intel_context_set_gem(ce, ctx, null_sseu); - engines->engines[0] = ce; - engines->num_engines = 1; - - mutex_lock(&ctx->engines_mutex); - i915_gem_context_set_user_engines(ctx); - engines = rcu_replace_pointer(ctx->engines, engines, 1); - mutex_unlock(&ctx->engines_mutex); - - engines_idle_release(ctx, engines); - - return ctx; -} - struct i915_gem_context * kernel_context(struct drm_i915_private *i915, struct i915_address_space *vm) diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.h b/drivers/gpu/drm/i915/gem/selftests/mock_context.h index 7a02fd9b5866..bc8fb37d2d24 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.h +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.h @@ -23,9 +23,6 @@ void mock_context_close(struct i915_gem_context *ctx); struct i915_gem_context * live_context(struct drm_i915_private *i915, struct file *file); -struct i915_gem_context * -live_context_for_engine(struct intel_engine_cs *engine, struct file *file); - struct i915_gem_context *kernel_context(struct drm_i915_private *i915, struct i915_address_space *vm); void kernel_context_close(struct i915_gem_context *ctx); -- cgit v1.2.3-59-g8ed1b From a4d1c5d0b99b75263a5626d2e52d569db3844b33 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Sat, 25 Jan 2025 22:55:05 +0100 Subject: drm/xe/pf: Move VFs reprovisioning to worker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the GuC is reset during GT reset, we need to re-send the entire SR-IOV provisioning configuration to the GuC. But since this whole configuration is protected by the PF master mutex and we can't avoid making allocations under this mutex (like during LMEM provisioning), we can't do this reprovisioning from gt-reset path if we want to be reclaim-safe. Move VFs reprovisioning to a async worker that we will start from the gt-reset path. Signed-off-by: Michal Wajdeczko Cc: Thomas Hellström Cc: Matthew Brost Reviewed-by: Michał Winiarski Reviewed-by: Stuart Summers Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250125215505.720-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf.c | 43 +++++++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h | 10 +++++++ 2 files changed, 51 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c index 6f906c8e8108..d66478deab98 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c @@ -15,7 +15,11 @@ #include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_migration.h" #include "xe_gt_sriov_pf_service.h" +#include "xe_gt_sriov_printk.h" #include "xe_mmio.h" +#include "xe_pm.h" + +static void pf_worker_restart_func(struct work_struct *w); /* * VF's metadata is maintained in the flexible array where: @@ -41,6 +45,11 @@ static int pf_alloc_metadata(struct xe_gt *gt) return 0; } +static void pf_init_workers(struct xe_gt *gt) +{ + INIT_WORK(>->sriov.pf.workers.restart, pf_worker_restart_func); +} + /** * xe_gt_sriov_pf_init_early - Prepare SR-IOV PF data structures on PF. * @gt: the &xe_gt to initialize @@ -65,6 +74,8 @@ int xe_gt_sriov_pf_init_early(struct xe_gt *gt) if (err) return err; + pf_init_workers(gt); + return 0; } @@ -155,6 +166,35 @@ void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid) pf_clear_vf_scratch_regs(gt, vfid); } +static void pf_restart(struct xe_gt *gt) +{ + struct xe_device *xe = gt_to_xe(gt); + + xe_pm_runtime_get(xe); + xe_gt_sriov_pf_config_restart(gt); + xe_gt_sriov_pf_control_restart(gt); + xe_pm_runtime_put(xe); + + xe_gt_sriov_dbg(gt, "restart completed\n"); +} + +static void pf_worker_restart_func(struct work_struct *w) +{ + struct xe_gt *gt = container_of(w, typeof(*gt), sriov.pf.workers.restart); + + pf_restart(gt); +} + +static void pf_queue_restart(struct xe_gt *gt) +{ + struct xe_device *xe = gt_to_xe(gt); + + xe_gt_assert(gt, IS_SRIOV_PF(xe)); + + if (!queue_work(xe->sriov.wq, >->sriov.pf.workers.restart)) + xe_gt_sriov_dbg(gt, "restart already in queue!\n"); +} + /** * xe_gt_sriov_pf_restart - Restart SR-IOV support after a GT reset. * @gt: the &xe_gt @@ -163,6 +203,5 @@ void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid) */ void xe_gt_sriov_pf_restart(struct xe_gt *gt) { - xe_gt_sriov_pf_config_restart(gt); - xe_gt_sriov_pf_control_restart(gt); + pf_queue_restart(gt); } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h index 0426b1a77069..a64a6835ad65 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h @@ -35,8 +35,17 @@ struct xe_gt_sriov_metadata { struct xe_gt_sriov_state_snapshot snapshot; }; +/** + * struct xe_gt_sriov_pf_workers - GT level workers used by the PF. + */ +struct xe_gt_sriov_pf_workers { + /** @restart: worker that executes actions post GT reset */ + struct work_struct restart; +}; + /** * struct xe_gt_sriov_pf - GT level PF virtualization data. + * @workers: workers data. * @service: service data. * @control: control data. * @policy: policy data. @@ -45,6 +54,7 @@ struct xe_gt_sriov_metadata { * @vfs: metadata for all VFs. */ struct xe_gt_sriov_pf { + struct xe_gt_sriov_pf_workers workers; struct xe_gt_sriov_pf_service service; struct xe_gt_sriov_pf_control control; struct xe_gt_sriov_pf_policy policy; -- cgit v1.2.3-59-g8ed1b From 2e0727c347467775a2dfa7d850a3a029f3212e58 Mon Sep 17 00:00:00 2001 From: Giedrius Statkevičius Date: Thu, 17 Oct 2024 10:57:24 +0300 Subject: drm/i915/lspcon: do not hardcode settle timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid hardcoding the LSPCON settle timeout because it takes a longer time on certain chips made by certain vendors. Use the function that already exists to determine the timeout. Reviewed-by: Ankit Nautiyal Signed-off-by: Giedrius Statkevičius Link: https://patchwork.freedesktop.org/patch/msgid/20241017075725.207384-1-giedriuswork@gmail.com Acked-by: Simona Vetter Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/display/drm_dp_dual_mode_helper.c | 4 ++-- drivers/gpu/drm/i915/display/intel_lspcon.c | 3 ++- include/drm/display/drm_dp_dual_mode_helper.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c index c491e3203bf1..4c350c7f5144 100644 --- a/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c @@ -486,16 +486,16 @@ EXPORT_SYMBOL(drm_lspcon_get_mode); * @dev: &drm_device to use * @adapter: I2C-over-aux adapter * @mode: required mode of operation + * @time_out: LSPCON mode change settle timeout * * Returns: * 0 on success, -error on failure/timeout */ int drm_lspcon_set_mode(const struct drm_device *dev, struct i2c_adapter *adapter, - enum drm_lspcon_mode mode) + enum drm_lspcon_mode mode, int time_out) { u8 data = 0; int ret; - int time_out = 200; enum drm_lspcon_mode current_mode; if (mode == DRM_LSPCON_MODE_PCON) diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index d75dd17fad32..0c8bf477c2fb 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -212,7 +212,8 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon, return 0; } - err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, ddc, mode); + err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, ddc, mode, + lspcon_get_mode_settle_timeout(lspcon)); if (err < 0) { drm_err(display->drm, "LSPCON mode change failed\n"); return err; diff --git a/include/drm/display/drm_dp_dual_mode_helper.h b/include/drm/display/drm_dp_dual_mode_helper.h index 7ee482265087..7ac6969db935 100644 --- a/include/drm/display/drm_dp_dual_mode_helper.h +++ b/include/drm/display/drm_dp_dual_mode_helper.h @@ -117,5 +117,5 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type); int drm_lspcon_get_mode(const struct drm_device *dev, struct i2c_adapter *adapter, enum drm_lspcon_mode *current_mode); int drm_lspcon_set_mode(const struct drm_device *dev, struct i2c_adapter *adapter, - enum drm_lspcon_mode reqd_mode); + enum drm_lspcon_mode reqd_mode, int time_out); #endif -- cgit v1.2.3-59-g8ed1b From ef34861098c081a6222dbbe84439b571fa35c8a0 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 17 Jan 2025 16:54:03 -0800 Subject: drm/xe: Upgrade complaint about missing slice info The steering code needs to know slice/subslice counts and this information should be retrieved from the hwconfig table. However, earlier platforms don't have it, hence the KMD has a fallback path. Newer platforms really should have the entries and if they are missing that is a bug that needs to be fixed in the table. So update the complaint to be an error on newer platforms and remove it completely for older ones that we know are bad (but are not POR for the Xe driver anyway). Also, re-word the message a little to make it clearer what the issue is. Signed-off-by: John Harrison Reviewed-by: Matt Roper Reviewed-by: Stuart Summers Acked-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250118005403.2960807-1-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/xe_gt_mcr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index a1676b787fdc..605aad3554e7 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -341,7 +341,13 @@ static unsigned int dss_per_group(struct xe_gt *gt) return DIV_ROUND_UP(max_subslices, max_slices); fallback: - xe_gt_dbg(gt, "GuC hwconfig cannot provide dss/slice; using typical fallback values\n"); + /* + * Some older platforms don't have tables or don't have complete tables. + * Newer platforms should always have the required info. + */ + if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 2000) + xe_gt_err(gt, "Slice/Subslice counts missing from hwconfig table; using typical fallback values\n"); + if (gt_to_xe(gt)->info.platform == XE_PVC) return 8; else if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1250) -- cgit v1.2.3-59-g8ed1b From 431b742e2bfc9f6dd713f261629741980996d001 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Thu, 23 Jan 2025 11:38:39 -0800 Subject: drm/i915/pmu: Fix zero delta busyness issue When running igt@gem_exec_balancer@individual for multiple iterations, it is seen that the delta busyness returned by PMU is 0. The issue stems from a combination of 2 implementation specific details: 1) gt_park is throttling __update_guc_busyness_stats() so that it does not hog PCI bandwidth for some use cases. (Ref: 59bcdb564b3ba) 2) busyness implementation always returns monotonically increasing counters. (Ref: cf907f6d29421) If an application queried an engine while it was active, engine->stats.guc.running is set to true. Following that, if all PM wakeref's are released, then gt is parked. At this time the throttling of __update_guc_busyness_stats() may result in a missed update to the running state of the engine (due to (1) above). This means subsequent calls to guc_engine_busyness() will think that the engine is still running and they will keep updating the cached counter (stats->total). This results in an inflated cached counter. Later when the application runs a workload and queries for busyness, we return the cached value since it is larger than the actual value (due to (2) above) All subsequent queries will return the same large (inflated) value, so the application sees a delta busyness of zero. Fix the issue by resetting the running state of engines each time intel_guc_busyness_park() is called. v2: (Rodrigo) - Use the correct tag in commit message - Drop the redundant wakeref check in guc_engine_busyness() and update commit message Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13366 Fixes: cf907f6d2942 ("i915/guc: Ensure busyness counter increases motonically") Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250123193839.2394694-1-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index a2812621625b..9be6764d3cd3 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1469,6 +1469,19 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) spin_unlock_irqrestore(&guc->timestamp.lock, flags); } +static void __update_guc_busyness_running_state(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct intel_engine_cs *engine; + enum intel_engine_id id; + unsigned long flags; + + spin_lock_irqsave(&guc->timestamp.lock, flags); + for_each_engine(engine, gt, id) + engine->stats.guc.running = false; + spin_unlock_irqrestore(&guc->timestamp.lock, flags); +} + static void __update_guc_busyness_stats(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -1619,6 +1632,9 @@ void intel_guc_busyness_park(struct intel_gt *gt) if (!guc_submission_initialized(guc)) return; + /* Assume no engines are running and set running state to false */ + __update_guc_busyness_running_state(guc); + /* * There is a race with suspend flow where the worker runs after suspend * and causes an unclaimed register access warning. Cancel the worker -- cgit v1.2.3-59-g8ed1b From a37934ea75d331fafa7fe80b6180642ba5193422 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 22 Jan 2025 21:11:11 -0800 Subject: drm/xe/devcoredump: Move exec queue snapshot to Contexts section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having the exec queue snapshot inside a "GuC CT" section was always wrong. Commit c28fd6c358db ("drm/xe/devcoredump: Improve section headings and add tile info") tried to fix that bug, but with that also broke the mesa tool that parses the devcoredump, hence it was reverted in commit 70fb86a85dc9 ("drm/xe: Revert some changes that break a mesa debug tool"). With the mesa tool also fixed, this can propagate as a fix on both kernel and userspace side to avoid unnecessary headache for a debug feature. Cc: John Harrison Cc: Julia Filipchuk Cc: José Roberto de Souza Cc: stable@vger.kernel.org Fixes: 70fb86a85dc9 ("drm/xe: Revert some changes that break a mesa debug tool") Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20250123051112.1938193-2-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_devcoredump.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c index 81dc7795c065..a7946a76777e 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.c +++ b/drivers/gpu/drm/xe/xe_devcoredump.c @@ -119,11 +119,7 @@ static ssize_t __xe_devcoredump_read(char *buffer, size_t count, drm_puts(&p, "\n**** GuC CT ****\n"); xe_guc_ct_snapshot_print(ss->guc.ct, &p); - /* - * Don't add a new section header here because the mesa debug decoder - * tool expects the context information to be in the 'GuC CT' section. - */ - /* drm_puts(&p, "\n**** Contexts ****\n"); */ + drm_puts(&p, "\n**** Contexts ****\n"); xe_guc_exec_queue_snapshot_print(ss->ge, &p); drm_puts(&p, "\n**** Job ****\n"); -- cgit v1.2.3-59-g8ed1b From 2c95bbf5002776117a69caed3b31c10bf7341bec Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 23 Jan 2025 12:22:03 -0800 Subject: drm/xe: Fix and re-enable xe_print_blob_ascii85() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 70fb86a85dc9 ("drm/xe: Revert some changes that break a mesa debug tool") partially reverted some changes to workaround breakage caused to mesa tools. However, in doing so it also broke fetching the GuC log via debugfs since xe_print_blob_ascii85() simply bails out. The fix is to avoid the extra newlines: the devcoredump interface is line-oriented and adding random newlines in the middle breaks it. If a tool is able to parse it by looking at the data and checking for chars that are out of the ascii85 space, it can still do so. A format change that breaks the line-oriented output on devcoredump however needs better coordination with existing tools. v2: Add suffix description comment v3: Reword explanation of xe_print_blob_ascii85() calling drm_puts() in a loop Reviewed-by: José Roberto de Souza Cc: John Harrison Cc: Julia Filipchuk Cc: José Roberto de Souza Cc: stable@vger.kernel.org Fixes: 70fb86a85dc9 ("drm/xe: Revert some changes that break a mesa debug tool") Fixes: ec1455ce7e35 ("drm/xe/devcoredump: Add ASCII85 dump helper function") Link: https://patchwork.freedesktop.org/patch/msgid/20250123202307.95103-2-jose.souza@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_devcoredump.c | 34 +++++++++++++--------------------- drivers/gpu/drm/xe/xe_devcoredump.h | 2 +- drivers/gpu/drm/xe/xe_guc_ct.c | 3 ++- drivers/gpu/drm/xe/xe_guc_log.c | 4 +++- 4 files changed, 19 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c index a7946a76777e..39fe485d2085 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.c +++ b/drivers/gpu/drm/xe/xe_devcoredump.c @@ -391,42 +391,34 @@ int xe_devcoredump_init(struct xe_device *xe) /** * xe_print_blob_ascii85 - print a BLOB to some useful location in ASCII85 * - * The output is split to multiple lines because some print targets, e.g. dmesg - * cannot handle arbitrarily long lines. Note also that printing to dmesg in - * piece-meal fashion is not possible, each separate call to drm_puts() has a - * line-feed automatically added! Therefore, the entire output line must be - * constructed in a local buffer first, then printed in one atomic output call. + * The output is split into multiple calls to drm_puts() because some print + * targets, e.g. dmesg, cannot handle arbitrarily long lines. These targets may + * add newlines, as is the case with dmesg: each drm_puts() call creates a + * separate line. * * There is also a scheduler yield call to prevent the 'task has been stuck for * 120s' kernel hang check feature from firing when printing to a slow target * such as dmesg over a serial port. * - * TODO: Add compression prior to the ASCII85 encoding to shrink huge buffers down. - * * @p: the printer object to output to * @prefix: optional prefix to add to output string + * @suffix: optional suffix to add at the end. 0 disables it and is + * not added to the output, which is useful when using multiple calls + * to dump data to @p * @blob: the Binary Large OBject to dump out * @offset: offset in bytes to skip from the front of the BLOB, must be a multiple of sizeof(u32) * @size: the size in bytes of the BLOB, must be a multiple of sizeof(u32) */ -void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, +void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, char suffix, const void *blob, size_t offset, size_t size) { const u32 *blob32 = (const u32 *)blob; char buff[ASCII85_BUFSZ], *line_buff; size_t line_pos = 0; - /* - * Splitting blobs across multiple lines is not compatible with the mesa - * debug decoder tool. Note that even dropping the explicit '\n' below - * doesn't help because the GuC log is so big some underlying implementation - * still splits the lines at 512K characters. So just bail completely for - * the moment. - */ - return; - #define DMESG_MAX_LINE_LEN 800 -#define MIN_SPACE (ASCII85_BUFSZ + 2) /* 85 + "\n\0" */ + /* Always leave space for the suffix char and the \0 */ +#define MIN_SPACE (ASCII85_BUFSZ + 2) /* 85 + "\0" */ if (size & 3) drm_printf(p, "Size not word aligned: %zu", size); @@ -458,7 +450,6 @@ void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, line_pos += strlen(line_buff + line_pos); if ((line_pos + MIN_SPACE) >= DMESG_MAX_LINE_LEN) { - line_buff[line_pos++] = '\n'; line_buff[line_pos++] = 0; drm_puts(p, line_buff); @@ -470,10 +461,11 @@ void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, } } + if (suffix) + line_buff[line_pos++] = suffix; + if (line_pos) { - line_buff[line_pos++] = '\n'; line_buff[line_pos++] = 0; - drm_puts(p, line_buff); } diff --git a/drivers/gpu/drm/xe/xe_devcoredump.h b/drivers/gpu/drm/xe/xe_devcoredump.h index 6a17e6d60102..5391a80a4d1b 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.h +++ b/drivers/gpu/drm/xe/xe_devcoredump.h @@ -29,7 +29,7 @@ static inline int xe_devcoredump_init(struct xe_device *xe) } #endif -void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, +void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, char suffix, const void *blob, size_t offset, size_t size); #endif diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 8b65c5e959cc..50c8076b5158 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -1724,7 +1724,8 @@ void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, snapshot->g2h_outstanding); if (snapshot->ctb) - xe_print_blob_ascii85(p, "CTB data", snapshot->ctb, 0, snapshot->ctb_size); + xe_print_blob_ascii85(p, "CTB data", '\n', + snapshot->ctb, 0, snapshot->ctb_size); } else { drm_puts(p, "CT disabled\n"); } diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c index 80151ff6a71f..44482ea91992 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.c +++ b/drivers/gpu/drm/xe/xe_guc_log.c @@ -207,8 +207,10 @@ void xe_guc_log_snapshot_print(struct xe_guc_log_snapshot *snapshot, struct drm_ remain = snapshot->size; for (i = 0; i < snapshot->num_chunks; i++) { size_t size = min(GUC_LOG_CHUNK_SIZE, remain); + const char *prefix = i ? NULL : "Log data"; + char suffix = i == snapshot->num_chunks - 1 ? '\n' : 0; - xe_print_blob_ascii85(p, i ? NULL : "Log data", snapshot->copy[i], 0, size); + xe_print_blob_ascii85(p, prefix, suffix, snapshot->copy[i], 0, size); remain -= size; } } -- cgit v1.2.3-59-g8ed1b From cb1f868ca13756c0c18ba54d1591332476760d07 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 23 Jan 2025 12:22:04 -0800 Subject: drm/xe: Make GUC binaries dump consistent with other binaries in devcoredump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All other(hwsp, hwctx and vmas) binaries follow this format: [name].length: 0x1000 [name].data: xxxxxxx [name].error: errno The error one is just in case by some reason it was not able to capture the binary. So this GuC binaries should follow the same patern. v2: - renamed GUC binary to LOG Cc: John Harrison Cc: Lucas De Marchi Reviewed-by: Lucas De Marchi Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20250123202307.95103-3-jose.souza@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_guc_ct.c | 6 ++++-- drivers/gpu/drm/xe/xe_guc_log.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 50c8076b5158..497036675a38 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -1723,9 +1723,11 @@ void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, drm_printf(p, "\tg2h outstanding: %d\n", snapshot->g2h_outstanding); - if (snapshot->ctb) - xe_print_blob_ascii85(p, "CTB data", '\n', + if (snapshot->ctb) { + drm_printf(p, "[CTB].length: 0x%lx\n", snapshot->ctb_size); + xe_print_blob_ascii85(p, "[CTB].data", '\n', snapshot->ctb, 0, snapshot->ctb_size); + } } else { drm_puts(p, "CT disabled\n"); } diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c index 44482ea91992..ab97ac728d7a 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.c +++ b/drivers/gpu/drm/xe/xe_guc_log.c @@ -204,10 +204,11 @@ void xe_guc_log_snapshot_print(struct xe_guc_log_snapshot *snapshot, struct drm_ drm_printf(p, "GuC timestamp: 0x%08llX [%llu]\n", snapshot->stamp, snapshot->stamp); drm_printf(p, "Log level: %u\n", snapshot->level); + drm_printf(p, "[LOG].length: 0x%lx\n", snapshot->size); remain = snapshot->size; for (i = 0; i < snapshot->num_chunks; i++) { size_t size = min(GUC_LOG_CHUNK_SIZE, remain); - const char *prefix = i ? NULL : "Log data"; + const char *prefix = i ? NULL : "[LOG].data"; char suffix = i == snapshot->num_chunks - 1 ? '\n' : 0; xe_print_blob_ascii85(p, prefix, suffix, snapshot->copy[i], 0, size); -- cgit v1.2.3-59-g8ed1b From 5e940312a2ac64ba0d6239aff72135226818b238 Mon Sep 17 00:00:00 2001 From: Riana Tauro Date: Tue, 28 Jan 2025 15:26:30 +0530 Subject: drm/xe: Add functions and sysfs for boot survivability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boot Survivability is a software based workflow for recovering a system in a failed boot state. Here system recoverability is concerned with recovering the firmware responsible for boot. This is implemented by loading the driver with bare minimum (no drm card) to allow the firmware to be flashed through mei-gsc and collect telemetry. The driver's probe flow is modified such that it enters survivability mode when pcode initialization is incomplete and boot status denotes a failure. In this mode, drm card is not exposed and presence of survivability_mode entry in PCI sysfs is used to indicate survivability mode and provide additional information required for debug This patch adds initialization functions and exposes admin readable sysfs entries The new sysfs will have the below layout /sys/bus/.../bdf ├── survivability_mode v2: reorder headers fix doc remove survivability info and use mode to display information use separate function for logging survivability information for critical error (Rodrigo) v3: use for loop use dev logs instead of drm use helper function for aux history(Rodrigo) remove unnecessary error check of greater than max_scratch as we are reading only 3 bit v4: fix checkpatch warnings fix space (Rodrigo) rename register Signed-off-by: Riana Tauro Acked-by: Ashwin Kumar Kulkarni Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250128095632.1294722-2-riana.tauro@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_device_types.h | 4 + drivers/gpu/drm/xe/xe_pcode_api.h | 14 ++ drivers/gpu/drm/xe/xe_survivability_mode.c | 215 +++++++++++++++++++++++ drivers/gpu/drm/xe/xe_survivability_mode.h | 17 ++ drivers/gpu/drm/xe/xe_survivability_mode_types.h | 35 ++++ 6 files changed, 286 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_survivability_mode.c create mode 100644 drivers/gpu/drm/xe/xe_survivability_mode.h create mode 100644 drivers/gpu/drm/xe/xe_survivability_mode_types.h (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 9122e4318773..ef900b9f0457 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -96,6 +96,7 @@ xe-y += xe_bb.o \ xe_sa.o \ xe_sched_job.o \ xe_step.o \ + xe_survivability_mode.o \ xe_sync.o \ xe_tile.o \ xe_tile_sysfs.o \ diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 58e79e19deaa..89f532b67bc4 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -22,6 +22,7 @@ #include "xe_pt_types.h" #include "xe_sriov_types.h" #include "xe_step_types.h" +#include "xe_survivability_mode_types.h" #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) #define TEST_VM_OPS_ERROR @@ -331,6 +332,9 @@ struct xe_device { u8 skip_pcode:1; } info; + /** @survivability: survivability information for device */ + struct xe_survivability survivability; + /** @irq: device interrupt state */ struct { /** @irq.lock: lock for processing irq's on this device */ diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h index f153ce96f69a..2bae9afdbd35 100644 --- a/drivers/gpu/drm/xe/xe_pcode_api.h +++ b/drivers/gpu/drm/xe/xe_pcode_api.h @@ -49,6 +49,20 @@ /* Domain IDs (param2) */ #define PCODE_MBOX_DOMAIN_HBM 0x2 +#define PCODE_SCRATCH(x) XE_REG(0x138320 + ((x) * 4)) +/* PCODE_SCRATCH0 */ +#define AUXINFO_REG_OFFSET REG_GENMASK(17, 15) +#define OVERFLOW_REG_OFFSET REG_GENMASK(14, 12) +#define HISTORY_TRACKING REG_BIT(11) +#define OVERFLOW_SUPPORT REG_BIT(10) +#define AUXINFO_SUPPORT REG_BIT(9) +#define BOOT_STATUS REG_GENMASK(3, 1) +#define CRITICAL_FAILURE 4 +#define NON_CRITICAL_FAILURE 7 + +/* Auxiliary info bits */ +#define AUXINFO_HISTORY_OFFSET REG_GENMASK(31, 29) + struct pcode_err_decode { int errno; const char *str; diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.c b/drivers/gpu/drm/xe/xe_survivability_mode.c new file mode 100644 index 000000000000..9911e9f6b99b --- /dev/null +++ b/drivers/gpu/drm/xe/xe_survivability_mode.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2025 Intel Corporation + */ + +#include "xe_survivability_mode.h" +#include "xe_survivability_mode_types.h" + +#include +#include +#include + +#include "xe_device.h" +#include "xe_gt.h" +#include "xe_mmio.h" +#include "xe_pcode_api.h" + +#define MAX_SCRATCH_MMIO 8 + +/** + * DOC: Xe Boot Survivability + * + * Boot Survivability is a software based workflow for recovering a system in a failed boot state + * Here system recoverability is concerned with recovering the firmware responsible for boot. + * + * This is implemented by loading the driver with bare minimum (no drm card) to allow the firmware + * to be flashed through mei and collect telemetry. The driver's probe flow is modified + * such that it enters survivability mode when pcode initialization is incomplete and boot status + * denotes a failure. The driver then populates the survivability_mode PCI sysfs indicating + * survivability mode and provides additional information required for debug + * + * KMD exposes below admin-only readable sysfs in survivability mode + * + * device/survivability_mode: The presence of this file indicates that the card is in survivability + * mode. Also, provides additional information on why the driver entered + * survivability mode. + * + * Capability Information - Provides boot status + * Postcode Information - Provides information about the failure + * Overflow Information - Provides history of previous failures + * Auxiliary Information - Certain failures may have information in + * addition to postcode information + */ + +static u32 aux_history_offset(u32 reg_value) +{ + return REG_FIELD_GET(AUXINFO_HISTORY_OFFSET, reg_value); +} + +static void set_survivability_info(struct xe_mmio *mmio, struct xe_survivability_info *info, + int id, char *name) +{ + strscpy(info[id].name, name, sizeof(info[id].name)); + info[id].reg = PCODE_SCRATCH(id).raw; + info[id].value = xe_mmio_read32(mmio, PCODE_SCRATCH(id)); +} + +static void populate_survivability_info(struct xe_device *xe) +{ + struct xe_survivability *survivability = &xe->survivability; + struct xe_survivability_info *info = survivability->info; + struct xe_mmio *mmio; + u32 id = 0, reg_value; + char name[NAME_MAX]; + int index; + + mmio = xe_root_tile_mmio(xe); + set_survivability_info(mmio, info, id, "Capability Info"); + reg_value = info[id].value; + + if (reg_value & HISTORY_TRACKING) { + id++; + set_survivability_info(mmio, info, id, "Postcode Info"); + + if (reg_value & OVERFLOW_SUPPORT) { + id = REG_FIELD_GET(OVERFLOW_REG_OFFSET, reg_value); + set_survivability_info(mmio, info, id, "Overflow Info"); + } + } + + if (reg_value & AUXINFO_SUPPORT) { + id = REG_FIELD_GET(AUXINFO_REG_OFFSET, reg_value); + + for (index = 0; id && reg_value; index++, reg_value = info[id].value, + id = aux_history_offset(reg_value)) { + snprintf(name, NAME_MAX, "Auxiliary Info %d", index); + set_survivability_info(mmio, info, id, name); + } + } +} + +static void log_survivability_info(struct pci_dev *pdev) +{ + struct xe_device *xe = pdev_to_xe_device(pdev); + struct xe_survivability *survivability = &xe->survivability; + struct xe_survivability_info *info = survivability->info; + int id; + + dev_info(&pdev->dev, "Survivability Boot Status : Critical Failure (%d)\n", + survivability->boot_status); + for (id = 0; id < MAX_SCRATCH_MMIO; id++) { + if (info[id].reg) + dev_info(&pdev->dev, "%s: 0x%x - 0x%x\n", info[id].name, + info[id].reg, info[id].value); + } +} + +static ssize_t survivability_mode_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct xe_device *xe = pdev_to_xe_device(pdev); + struct xe_survivability *survivability = &xe->survivability; + struct xe_survivability_info *info = survivability->info; + int index = 0, count = 0; + + for (index = 0; index < MAX_SCRATCH_MMIO; index++) { + if (info[index].reg) + count += sysfs_emit_at(buff, count, "%s: 0x%x - 0x%x\n", info[index].name, + info[index].reg, info[index].value); + } + + return count; +} + +static DEVICE_ATTR_ADMIN_RO(survivability_mode); + +static void enable_survivability_mode(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct xe_device *xe = pdev_to_xe_device(pdev); + struct xe_survivability *survivability = &xe->survivability; + int ret = 0; + + /* set survivability mode */ + survivability->mode = true; + dev_info(dev, "In Survivability Mode\n"); + + /* create survivability mode sysfs */ + ret = sysfs_create_file(&dev->kobj, &dev_attr_survivability_mode.attr); + if (ret) { + dev_warn(dev, "Failed to create survivability sysfs files\n"); + return; + } +} + +/** + * xe_survivability_mode_required - checks if survivability mode is required + * @xe: xe device instance + * + * This function reads the boot status from Pcode + * + * Return: true if boot status indicates failure, false otherwise + */ +bool xe_survivability_mode_required(struct xe_device *xe) +{ + struct xe_survivability *survivability = &xe->survivability; + struct xe_mmio *mmio = xe_root_tile_mmio(xe); + u32 data; + + data = xe_mmio_read32(mmio, PCODE_SCRATCH(0)); + survivability->boot_status = REG_FIELD_GET(BOOT_STATUS, data); + + return (survivability->boot_status == NON_CRITICAL_FAILURE || + survivability->boot_status == CRITICAL_FAILURE); +} + +/** + * xe_survivability_mode_remove - remove survivability mode + * @xe: xe device instance + * + * clean up sysfs entries of survivability mode + */ +void xe_survivability_mode_remove(struct xe_device *xe) +{ + struct xe_survivability *survivability = &xe->survivability; + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + struct device *dev = &pdev->dev; + + sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr); + kfree(survivability->info); + pci_set_drvdata(pdev, NULL); +} + +/** + * xe_survivability_mode_init - Initialize the survivability mode + * @xe: xe device instance + * + * Initializes survivability information and enables survivability mode + */ +void xe_survivability_mode_init(struct xe_device *xe) +{ + struct xe_survivability *survivability = &xe->survivability; + struct xe_survivability_info *info; + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + + survivability->size = MAX_SCRATCH_MMIO; + + info = kcalloc(survivability->size, sizeof(*info), GFP_KERNEL); + if (!info) + return; + + survivability->info = info; + + populate_survivability_info(xe); + + /* Only log debug information and exit if it is a critical failure */ + if (survivability->boot_status == CRITICAL_FAILURE) { + log_survivability_info(pdev); + kfree(survivability->info); + return; + } + + enable_survivability_mode(pdev); +} diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.h b/drivers/gpu/drm/xe/xe_survivability_mode.h new file mode 100644 index 000000000000..410e3ee5f5d1 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_survivability_mode.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2025 Intel Corporation + */ + +#ifndef _XE_SURVIVABILITY_MODE_H_ +#define _XE_SURVIVABILITY_MODE_H_ + +#include + +struct xe_device; + +void xe_survivability_mode_init(struct xe_device *xe); +void xe_survivability_mode_remove(struct xe_device *xe); +bool xe_survivability_mode_required(struct xe_device *xe); + +#endif /* _XE_SURVIVABILITY_MODE_H_ */ diff --git a/drivers/gpu/drm/xe/xe_survivability_mode_types.h b/drivers/gpu/drm/xe/xe_survivability_mode_types.h new file mode 100644 index 000000000000..19d433e253df --- /dev/null +++ b/drivers/gpu/drm/xe/xe_survivability_mode_types.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2025 Intel Corporation + */ + +#ifndef _XE_SURVIVABILITY_MODE_TYPES_H_ +#define _XE_SURVIVABILITY_MODE_TYPES_H_ + +#include +#include + +struct xe_survivability_info { + char name[NAME_MAX]; + u32 reg; + u32 value; +}; + +/** + * struct xe_survivability: Contains survivability mode information + */ +struct xe_survivability { + /** @info: struct that holds survivability info from scratch registers */ + struct xe_survivability_info *info; + + /** @size: number of scratch registers */ + u32 size; + + /** @boot_status: indicates critical/non critical boot failure */ + u8 boot_status; + + /** @mode: boolean to indicate survivability mode */ + bool mode; +}; + +#endif /* _XE_SURVIVABILITY_MODE_TYPES_H_ */ -- cgit v1.2.3-59-g8ed1b From 256daa32c9e0dcf924b3237e2165d8163f4d89cc Mon Sep 17 00:00:00 2001 From: Riana Tauro Date: Tue, 28 Jan 2025 15:26:31 +0530 Subject: drm/xe: Enable Boot Survivability mode Enable boot survivability mode if pcode initialization fails and if boot status indicates a failure. In this mode, drm card is not exposed and driver probe returns success after loading the bare minimum to allow firmware to be flashed via mei. v2: abstract survivability mode variable add BMG check inside function (Jani, Rodrigo) v3: return -EBUSY during system suspend (Anshuman) check survivability mode in pci probe only on error Signed-off-by: Riana Tauro Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250128095632.1294722-3-riana.tauro@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_device.c | 7 ++++++- drivers/gpu/drm/xe/xe_pci.c | 23 +++++++++++++++++++++-- drivers/gpu/drm/xe/xe_survivability_mode.c | 16 ++++++++++++++++ drivers/gpu/drm/xe/xe_survivability_mode.h | 1 + 4 files changed, 44 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 90597a7ad0b0..37ea1c099a67 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -52,6 +52,7 @@ #include "xe_pmu.h" #include "xe_query.h" #include "xe_sriov.h" +#include "xe_survivability_mode.h" #include "xe_tile.h" #include "xe_ttm_stolen_mgr.h" #include "xe_ttm_sys_mgr.h" @@ -694,8 +695,12 @@ int xe_device_probe_early(struct xe_device *xe) update_device_info(xe); err = xe_pcode_probe_early(xe); - if (err) + if (err) { + if (xe_survivability_mode_required(xe)) + xe_survivability_mode_init(xe); + return err; + } err = wait_for_lmem_ready(xe); if (err) diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index bf35a18bf5e7..f05cf26a088c 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -30,6 +30,7 @@ #include "xe_pm.h" #include "xe_sriov.h" #include "xe_step.h" +#include "xe_survivability_mode.h" #include "xe_tile.h" enum toggle_d3cold { @@ -761,6 +762,9 @@ static void xe_pci_remove(struct pci_dev *pdev) if (IS_SRIOV_PF(xe)) xe_pci_sriov_configure(pdev, 0); + if (xe_survivability_mode_enabled(xe)) + return xe_survivability_mode_remove(xe); + xe_device_remove(xe); xe_pm_runtime_fini(xe); pci_set_drvdata(pdev, NULL); @@ -833,8 +837,19 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; err = xe_device_probe_early(xe); - if (err) + + /* + * In Boot Survivability mode, no drm card is exposed + * and driver is loaded with bare minimum to allow + * for firmware to be flashed through mei. Return + * success if survivability mode is enabled. + */ + if (err) { + if (xe_survivability_mode_enabled(xe)) + return 0; + return err; + } err = xe_info_init(xe, desc->graphics, desc->media); if (err) @@ -921,9 +936,13 @@ static void d3cold_toggle(struct pci_dev *pdev, enum toggle_d3cold toggle) static int xe_pci_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); + struct xe_device *xe = pdev_to_xe_device(pdev); int err; - err = xe_pm_suspend(pdev_to_xe_device(pdev)); + if (xe_survivability_mode_enabled(xe)) + return -EBUSY; + + err = xe_pm_suspend(xe); if (err) return err; diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.c b/drivers/gpu/drm/xe/xe_survivability_mode.c index 9911e9f6b99b..633f5effa349 100644 --- a/drivers/gpu/drm/xe/xe_survivability_mode.c +++ b/drivers/gpu/drm/xe/xe_survivability_mode.c @@ -144,6 +144,19 @@ static void enable_survivability_mode(struct pci_dev *pdev) } } +/** + * xe_survivability_mode_enabled - check if survivability mode is enabled + * @xe: xe device instance + * + * Returns true if in survivability mode, false otherwise + */ +bool xe_survivability_mode_enabled(struct xe_device *xe) +{ + struct xe_survivability *survivability = &xe->survivability; + + return survivability->mode; +} + /** * xe_survivability_mode_required - checks if survivability mode is required * @xe: xe device instance @@ -158,6 +171,9 @@ bool xe_survivability_mode_required(struct xe_device *xe) struct xe_mmio *mmio = xe_root_tile_mmio(xe); u32 data; + if (!IS_DGFX(xe) || xe->info.platform < XE_BATTLEMAGE) + return false; + data = xe_mmio_read32(mmio, PCODE_SCRATCH(0)); survivability->boot_status = REG_FIELD_GET(BOOT_STATUS, data); diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.h b/drivers/gpu/drm/xe/xe_survivability_mode.h index 410e3ee5f5d1..f530507a22c6 100644 --- a/drivers/gpu/drm/xe/xe_survivability_mode.h +++ b/drivers/gpu/drm/xe/xe_survivability_mode.h @@ -12,6 +12,7 @@ struct xe_device; void xe_survivability_mode_init(struct xe_device *xe); void xe_survivability_mode_remove(struct xe_device *xe); +bool xe_survivability_mode_enabled(struct xe_device *xe); bool xe_survivability_mode_required(struct xe_device *xe); #endif /* _XE_SURVIVABILITY_MODE_H_ */ -- cgit v1.2.3-59-g8ed1b From 8b47c9cdb6a78364fe68f8af0abfd6f265577001 Mon Sep 17 00:00:00 2001 From: Riana Tauro Date: Tue, 28 Jan 2025 15:26:32 +0530 Subject: drm/xe: Initialize mei-gsc and vsec in survivability mode Initialize mei-gsc in survivability mode and disable HECI interrupts. Also initialize vsec in survivability mode Signed-off-by: Riana Tauro Reviewed-by: Rodrigo Vivi Reviewed-by: Alexander Usyskin Link: https://patchwork.freedesktop.org/patch/msgid/20250128095632.1294722-4-riana.tauro@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_heci_gsc.c | 3 ++- drivers/gpu/drm/xe/xe_survivability_mode.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.c b/drivers/gpu/drm/xe/xe_heci_gsc.c index d765bfd3636b..06dc78d3a812 100644 --- a/drivers/gpu/drm/xe/xe_heci_gsc.c +++ b/drivers/gpu/drm/xe/xe_heci_gsc.c @@ -12,6 +12,7 @@ #include "xe_drv.h" #include "xe_heci_gsc.h" #include "xe_platform_types.h" +#include "xe_survivability_mode.h" #define GSC_BAR_LENGTH 0x00000FFC @@ -200,7 +201,7 @@ void xe_heci_gsc_init(struct xe_device *xe) return; } - if (!def->use_polling) { + if (!def->use_polling && !xe_survivability_mode_enabled(xe)) { ret = heci_gsc_irq_setup(xe); if (ret) goto fail; diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.c b/drivers/gpu/drm/xe/xe_survivability_mode.c index 633f5effa349..c619560af74f 100644 --- a/drivers/gpu/drm/xe/xe_survivability_mode.c +++ b/drivers/gpu/drm/xe/xe_survivability_mode.c @@ -12,8 +12,10 @@ #include "xe_device.h" #include "xe_gt.h" +#include "xe_heci_gsc.h" #include "xe_mmio.h" #include "xe_pcode_api.h" +#include "xe_vsec.h" #define MAX_SCRATCH_MMIO 8 @@ -142,6 +144,10 @@ static void enable_survivability_mode(struct pci_dev *pdev) dev_warn(dev, "Failed to create survivability sysfs files\n"); return; } + + xe_heci_gsc_init(xe); + + xe_vsec_init(xe); } /** @@ -194,6 +200,7 @@ void xe_survivability_mode_remove(struct xe_device *xe) struct device *dev = &pdev->dev; sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr); + xe_heci_gsc_fini(xe); kfree(survivability->info); pci_set_drvdata(pdev, NULL); } -- cgit v1.2.3-59-g8ed1b From 9e304a18630875352636ad52a3d2af47c3bde824 Mon Sep 17 00:00:00 2001 From: Brian Geffon Date: Mon, 27 Jan 2025 15:43:32 -0500 Subject: drm/i915: Fix page cleanup on DMA remap failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When converting to folios the cleanup path of shmem_get_pages() was missed. When a DMA remap fails and the max segment size is greater than PAGE_SIZE it will attempt to retry the remap with a PAGE_SIZEd segment size. The cleanup code isn't properly using the folio apis and as a result isn't handling compound pages correctly. v2 -> v3: (Ville) Just use shmem_sg_free_table() as-is in the failure path of shmem_get_pages(). shmem_sg_free_table() will clear mapping unevictable but it will be reset when it retries in shmem_sg_alloc_table(). v1 -> v2: (Ville) Fixed locations where we were not clearing mapping unevictable. Cc: stable@vger.kernel.org Cc: Ville Syrjala Cc: Vidya Srinivas Link: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13487 Link: https://lore.kernel.org/lkml/20250116135636.410164-1-bgeffon@google.com/ Fixes: 0b62af28f249 ("i915: convert shmem_sg_free_table() to use a folio_batch") Signed-off-by: Brian Geffon Suggested-by: Tomasz Figa Link: https://patchwork.freedesktop.org/patch/msgid/20250127204332.336665-1-bgeffon@google.com Reviewed-by: Jonathan Cavitt Tested-by: Vidya Srinivas Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index c5e1c718a6d2..1e202e7f4efd 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -209,8 +209,6 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) struct address_space *mapping = obj->base.filp->f_mapping; unsigned int max_segment = i915_sg_segment_size(i915->drm.dev); struct sg_table *st; - struct sgt_iter sgt_iter; - struct page *page; int ret; /* @@ -239,9 +237,7 @@ rebuild_st: * for PAGE_SIZE chunks instead may be helpful. */ if (max_segment > PAGE_SIZE) { - for_each_sgt_page(page, sgt_iter, st) - put_page(page); - sg_free_table(st); + shmem_sg_free_table(st, mapping, false, false); kfree(st); max_segment = PAGE_SIZE; -- cgit v1.2.3-59-g8ed1b From 35e1aacfe536d6e8d8d440cd7155366da2541ad4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 18 Dec 2024 19:36:47 +0200 Subject: drm/i915: Drop 64bpp YUV formats from ICL+ SDR planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm seeing underruns with these 64bpp YUV formats on TGL. The weird details: - only happens on pipe B/C/D SDR planes, pipe A SDR planes seem fine, as do all HDR planes - somehow CDCLK related, higher CDCLK allows for bigger plane with these formats without underruns. With 300MHz CDCLK I can only go up to 1200 pixels wide or so, with 650MHz even a 3840 pixel wide plane was OK - ICL and ADL so far appear unaffected So not really sure what's the deal with this, but bspec does state "64-bit formats supported only on the HDR planes" so let's just drop these formats from the SDR planes. We already disallow 64bpp RGB formats. Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241218173650.19782-2-ville.syrjala@linux.intel.com Reviewed-by: Juha-Pekka Heikkila --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 301ad3a22c4c..ba5db553c374 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -106,8 +106,6 @@ static const u32 icl_sdr_y_plane_formats[] = { DRM_FORMAT_Y216, DRM_FORMAT_XYUV8888, DRM_FORMAT_XVYU2101010, - DRM_FORMAT_XVYU12_16161616, - DRM_FORMAT_XVYU16161616, }; static const u32 icl_sdr_uv_plane_formats[] = { @@ -134,8 +132,6 @@ static const u32 icl_sdr_uv_plane_formats[] = { DRM_FORMAT_Y216, DRM_FORMAT_XYUV8888, DRM_FORMAT_XVYU2101010, - DRM_FORMAT_XVYU12_16161616, - DRM_FORMAT_XVYU16161616, }; static const u32 icl_hdr_plane_formats[] = { -- cgit v1.2.3-59-g8ed1b From 9548f4f4bd80d1abbbae3024fdb6a4b2e9a1690a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 18 Dec 2024 19:36:48 +0200 Subject: drm/i915: Drop the extra "plane" from tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Out plane names already include the "plane" part (or "primary","sprite","cursor" in some cases). Don't duplicate that in the tracepoints as that leadst to weird stuff like "plane plane 1A". Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241218173650.19782-3-ville.syrjala@linux.intel.com Reviewed-by: Juha-Pekka Heikkila --- drivers/gpu/drm/i915/display/intel_display_trace.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 54a6e2a46b82..989d6f0f3c42 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -397,7 +397,7 @@ TRACE_EVENT(intel_plane_async_flip, __entry->async_flip = async_flip; ), - TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, async_flip=%s", + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, async_flip=%s", __get_str(dev), __entry->pipe_name, __get_str(name), __entry->frame, __entry->scanline, str_yes_no(__entry->async_flip)) ); @@ -426,7 +426,7 @@ TRACE_EVENT(intel_plane_update_noarm, memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst)); ), - TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, __get_str(dev), __entry->pipe_name, __get_str(name), __entry->frame, __entry->scanline, DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src), @@ -457,7 +457,7 @@ TRACE_EVENT(intel_plane_update_arm, memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst)); ), - TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, __get_str(dev), __entry->pipe_name, __get_str(name), __entry->frame, __entry->scanline, DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src), @@ -484,7 +484,7 @@ TRACE_EVENT(intel_plane_disable_arm, __entry->scanline = intel_get_crtc_scanline(crtc); ), - TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u", + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u", __get_str(dev), __entry->pipe_name, __get_str(name), __entry->frame, __entry->scanline) ); @@ -611,7 +611,7 @@ TRACE_EVENT(intel_fbc_activate, __entry->scanline = intel_get_crtc_scanline(crtc); ), - TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u", + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u", __get_str(dev), __entry->pipe_name, __get_str(name), __entry->frame, __entry->scanline) ); @@ -639,7 +639,7 @@ TRACE_EVENT(intel_fbc_deactivate, __entry->scanline = intel_get_crtc_scanline(crtc); ), - TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u", + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u", __get_str(dev), __entry->pipe_name, __get_str(name), __entry->frame, __entry->scanline) ); @@ -667,7 +667,7 @@ TRACE_EVENT(intel_fbc_nuke, __entry->scanline = intel_get_crtc_scanline(crtc); ), - TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u", + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u", __get_str(dev), __entry->pipe_name, __get_str(name), __entry->frame, __entry->scanline) ); -- cgit v1.2.3-59-g8ed1b From 8cebc86c8275417e03945557bc33a4c9fc8e7824 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 18 Dec 2024 19:36:49 +0200 Subject: drm/i915: Pass the plane state explicitly to tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the plane->state pointer in the tracepoints is incorrect as technically a different state could already have been swapped in (though in reality that is currently prevented by the stall hacks in the commit machinery). But let's not leave such footguns lying around when we can just pass in the correct state by hand. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241218173650.19782-4-ville.syrjala@linux.intel.com Reviewed-by: Juha-Pekka Heikkila --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_trace.h | 25 +++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index c558143f4f82..651f81ed85ab 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -772,7 +772,7 @@ void intel_plane_update_noarm(struct intel_dsb *dsb, { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - trace_intel_plane_update_noarm(plane, crtc); + trace_intel_plane_update_noarm(plane_state, crtc); if (plane->update_noarm) plane->update_noarm(dsb, plane, crtc_state, plane_state); @@ -802,7 +802,7 @@ void intel_plane_update_arm(struct intel_dsb *dsb, return; } - trace_intel_plane_update_arm(plane, crtc); + trace_intel_plane_update_arm(plane_state, crtc); plane->update_arm(dsb, plane, crtc_state, plane_state); } diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 989d6f0f3c42..4fe65452e555 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -21,6 +21,7 @@ #include "intel_vblank.h" #define __dev_name_display(display) dev_name((display)->drm->dev) +#define __dev_name_drm(obj) dev_name((obj)->dev->dev) #define __dev_name_kms(obj) dev_name((obj)->base.dev->dev) /* @@ -403,17 +404,17 @@ TRACE_EVENT(intel_plane_async_flip, ); TRACE_EVENT(intel_plane_update_noarm, - TP_PROTO(struct intel_plane *plane, struct intel_crtc *crtc), - TP_ARGS(plane, crtc), + TP_PROTO(const struct intel_plane_state *plane_state, struct intel_crtc *crtc), + TP_ARGS(plane_state, crtc), TP_STRUCT__entry( - __string(dev, __dev_name_kms(plane)) + __string(dev, __dev_name_drm(plane_state->uapi.plane)) __field(char, pipe_name) __field(u32, frame) __field(u32, scanline) __array(int, src, 4) __array(int, dst, 4) - __string(name, plane->base.name) + __string(name, plane_state->uapi.plane->name) ), TP_fast_assign( @@ -422,8 +423,8 @@ TRACE_EVENT(intel_plane_update_noarm, __entry->pipe_name = pipe_name(crtc->pipe); __entry->frame = intel_crtc_get_vblank_counter(crtc); __entry->scanline = intel_get_crtc_scanline(crtc); - memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src)); - memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst)); + memcpy(__entry->src, &plane_state->uapi.src, sizeof(__entry->src)); + memcpy(__entry->dst, &plane_state->uapi.dst, sizeof(__entry->dst)); ), TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, @@ -434,17 +435,17 @@ TRACE_EVENT(intel_plane_update_noarm, ); TRACE_EVENT(intel_plane_update_arm, - TP_PROTO(struct intel_plane *plane, struct intel_crtc *crtc), - TP_ARGS(plane, crtc), + TP_PROTO(const struct intel_plane_state *plane_state, struct intel_crtc *crtc), + TP_ARGS(plane_state, crtc), TP_STRUCT__entry( - __string(dev, __dev_name_kms(plane)) + __string(dev, __dev_name_drm(plane_state->uapi.plane)) __field(char, pipe_name) __field(u32, frame) __field(u32, scanline) __array(int, src, 4) __array(int, dst, 4) - __string(name, plane->base.name) + __string(name, plane_state->uapi.plane->name) ), TP_fast_assign( @@ -453,8 +454,8 @@ TRACE_EVENT(intel_plane_update_arm, __entry->pipe_name = pipe_name(crtc->pipe); __entry->frame = intel_crtc_get_vblank_counter(crtc); __entry->scanline = intel_get_crtc_scanline(crtc); - memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src)); - memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst)); + memcpy(__entry->src, &plane_state->uapi.src, sizeof(__entry->src)); + memcpy(__entry->dst, &plane_state->uapi.dst, sizeof(__entry->dst)); ), TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, -- cgit v1.2.3-59-g8ed1b From 55f16199c2a95c7c1833daf8c6f2701cc7098023 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 18 Dec 2024 19:36:50 +0200 Subject: drm/i915: Include pixel format in plane tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make debugging a bit easier by including the pixel format in the plane tracepoints. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20241218173650.19782-5-ville.syrjala@linux.intel.com Reviewed-by: Juha-Pekka Heikkila --- drivers/gpu/drm/i915/display/intel_display_trace.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 4fe65452e555..9e85670b91e3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -412,6 +412,7 @@ TRACE_EVENT(intel_plane_update_noarm, __field(char, pipe_name) __field(u32, frame) __field(u32, scanline) + __field(u32, format) __array(int, src, 4) __array(int, dst, 4) __string(name, plane_state->uapi.plane->name) @@ -423,13 +424,14 @@ TRACE_EVENT(intel_plane_update_noarm, __entry->pipe_name = pipe_name(crtc->pipe); __entry->frame = intel_crtc_get_vblank_counter(crtc); __entry->scanline = intel_get_crtc_scanline(crtc); + __entry->format = plane_state->hw.fb->format->format; memcpy(__entry->src, &plane_state->uapi.src, sizeof(__entry->src)); memcpy(__entry->dst, &plane_state->uapi.dst, sizeof(__entry->dst)); ), - TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, format=%p4cc, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, __get_str(dev), __entry->pipe_name, __get_str(name), - __entry->frame, __entry->scanline, + __entry->frame, __entry->scanline, &__entry->format, DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src), DRM_RECT_ARG((const struct drm_rect *)__entry->dst)) ); @@ -443,6 +445,7 @@ TRACE_EVENT(intel_plane_update_arm, __field(char, pipe_name) __field(u32, frame) __field(u32, scanline) + __field(u32, format) __array(int, src, 4) __array(int, dst, 4) __string(name, plane_state->uapi.plane->name) @@ -454,13 +457,14 @@ TRACE_EVENT(intel_plane_update_arm, __entry->pipe_name = pipe_name(crtc->pipe); __entry->frame = intel_crtc_get_vblank_counter(crtc); __entry->scanline = intel_get_crtc_scanline(crtc); + __entry->format = plane_state->hw.fb->format->format; memcpy(__entry->src, &plane_state->uapi.src, sizeof(__entry->src)); memcpy(__entry->dst, &plane_state->uapi.dst, sizeof(__entry->dst)); ), - TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, + TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, format=%p4cc, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT, __get_str(dev), __entry->pipe_name, __get_str(name), - __entry->frame, __entry->scanline, + __entry->frame, __entry->scanline, &__entry->format, DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src), DRM_RECT_ARG((const struct drm_rect *)__entry->dst)) ); -- cgit v1.2.3-59-g8ed1b From 8305d47333d8e178890ae4990c7f0c8dbf5f4ace Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 27 Jan 2025 23:30:55 +0200 Subject: drm/i915: Give i915 and xe each their own display tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we just define the display tracepoints with TRACE_SYSTEM i915. However the code gets included separately in i915 and xe, and now both modules are competing for the same tracepoints. Apparently whichever module is loaded first gets the tracepoints and the other guy is left with nothing. Give each module its own set of display tracepoints so that things work even when both modules are loaded. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250127213055.640-1-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi Reviewed-by: Jonathan Cavitt --- drivers/gpu/drm/i915/display/intel_display_trace.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 9e85670b91e3..27ebc32cb61a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -4,7 +4,11 @@ */ #undef TRACE_SYSTEM +#ifdef I915 #define TRACE_SYSTEM i915 +#else +#define TRACE_SYSTEM xe +#endif #if !defined(__INTEL_DISPLAY_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) #define __INTEL_DISPLAY_TRACE_H__ -- cgit v1.2.3-59-g8ed1b From 1aeb1c0eda6060a57e078fbda263eb812dffaab1 Mon Sep 17 00:00:00 2001 From: Ranu Maurya Date: Thu, 16 Jan 2025 15:01:15 +0530 Subject: drm/i915: Add Wa_22010465259 in its respective WA list Add Wa_22010465259 which points to an existing WA, but was missing from the comment list. While at it, update the other WAs and their applicable platforms as well. v1: Initial commit. v2: Add DG2 platform to Wa_22010465259. v3: Removed DG2 platform to Wa_22010465259 since it was for preproduction. Signed-off-by: Ranu Maurya Reviewed-by: Balasubramani Vivekanandan Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20250116093115.2437154-1-ranu.maurya@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index e539a656cfc3..f3f99c5f458c 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -691,16 +691,17 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, struct drm_i915_private *i915 = engine->i915; /* - * Wa_1409142259:tgl,dg1,adl-p + * Wa_1409142259:tgl,dg1,adl-p,adl-n * Wa_1409347922:tgl,dg1,adl-p * Wa_1409252684:tgl,dg1,adl-p * Wa_1409217633:tgl,dg1,adl-p * Wa_1409207793:tgl,dg1,adl-p - * Wa_1409178076:tgl,dg1,adl-p - * Wa_1408979724:tgl,dg1,adl-p - * Wa_14010443199:tgl,rkl,dg1,adl-p - * Wa_14010698770:tgl,rkl,dg1,adl-s,adl-p - * Wa_1409342910:tgl,rkl,dg1,adl-s,adl-p + * Wa_1409178076:tgl,dg1,adl-p,adl-n + * Wa_1408979724:tgl,dg1,adl-p,adl-n + * Wa_14010443199:tgl,rkl,dg1,adl-p,adl-n + * Wa_14010698770:tgl,rkl,dg1,adl-s,adl-p,adl-n + * Wa_1409342910:tgl,rkl,dg1,adl-s,adl-p,adl-n + * Wa_22010465259:tgl,rkl,dg1,adl-s,adl-p,adl-n */ wa_masked_en(wal, GEN11_COMMON_SLICE_CHICKEN3, GEN12_DISABLE_CPS_AWARE_COLOR_PIPE); -- cgit v1.2.3-59-g8ed1b From d7364b86e4e59f7579061fed41e85a7cba14cfe6 Mon Sep 17 00:00:00 2001 From: Sk Anirban Date: Mon, 13 Jan 2025 15:29:11 +0530 Subject: drm/i915/selftests: Correct frequency handling in RPS power measurement Fix the frequency calculation by ensuring it uses the raw frequency only. Update live_rps_power test to use the correct frequency values for logging and comparison. Signed-off-by: Sk Anirban Reviewed-by: Badal Nilawar Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20250113095912.356147-2-sk.anirban@intel.com --- drivers/gpu/drm/i915/gt/selftest_rps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index 2d342bd61a31..2f4b1268af47 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -1116,7 +1116,7 @@ static u64 measure_power(struct intel_rps *rps, int *freq) for (i = 0; i < 5; i++) x[i] = __measure_power(5); - *freq = (*freq + intel_rps_read_actual_frequency(rps)) / 2; + *freq = (*freq + read_cagf(rps)) / 2; /* A simple triangle filter for better result stability */ sort(x, 5, sizeof(*x), cmp_u64, NULL); -- cgit v1.2.3-59-g8ed1b From 54cb7288900ba964bd525d004b9618efb52f724b Mon Sep 17 00:00:00 2001 From: Sk Anirban Date: Mon, 13 Jan 2025 15:29:12 +0530 Subject: drm/i915/guc/slpc: Add helper function slpc_measure_power Previously, the RPS function was being used, which utilizes raw frequency to calculate measured power. This commit introduces a dedicated function specifically for measuring power in SLPC, ensuring more accurate and reliable power measurements. Signed-off-by: Sk Anirban Reviewed-by: Badal Nilawar Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20250113095912.356147-3-sk.anirban@intel.com --- drivers/gpu/drm/i915/gt/selftest_slpc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c index 4ecc4ae74a54..cb5d5e2c5dbe 100644 --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -95,6 +95,21 @@ static int slpc_restore_freq(struct intel_guc_slpc *slpc, u32 min, u32 max) return 0; } +static u64 slpc_measure_power(struct intel_rps *rps, int *freq) +{ + u64 x[5]; + int i; + + for (i = 0; i < 5; i++) + x[i] = __measure_power(5); + + *freq = (*freq + intel_rps_read_actual_frequency(rps)) / 2; + + /* A simple triangle filter for better result stability */ + sort(x, 5, sizeof(*x), cmp_u64, NULL); + return div_u64(x[1] + 2 * x[2] + x[3], 4); +} + static u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power) { int err = 0; @@ -103,7 +118,7 @@ static u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power) if (err) return err; *freq = intel_rps_read_actual_frequency(>->rps); - *power = measure_power(>->rps, freq); + *power = slpc_measure_power(>->rps, freq); return err; } -- cgit v1.2.3-59-g8ed1b From c28f72c6ca98e039c2aa5aac6752c416bc31dbab Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Fri, 24 Jan 2025 15:11:31 +0100 Subject: drm/ast: Fix ast_dp connection status ast_dp_is_connected() used to also check for link training success to report the DP connector as connected. Without this check, the physical_status is always connected. So if no monitor is present, it will fail to read the EDID and set the default resolution to 640x480 instead of 1024x768. Signed-off-by: Jocelyn Falempe Fixes: 2281475168d2 ("drm/ast: astdp: Perform link training during atomic_enable") Reported-by: Jerry Hoemann Tested-by: Jose Lopez Cc: Thomas Zimmermann Cc: Dave Airlie Cc: dri-devel@lists.freedesktop.org Cc: # v6.12+ Reviewed-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250124141142.2434138-1-jfalempe@redhat.com --- drivers/gpu/drm/ast/ast_dp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 0e282b7b167c..30aad5c0112a 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -17,6 +17,12 @@ static bool ast_astdp_is_connected(struct ast_device *ast) { if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, AST_IO_VGACRDF_HPD)) return false; + /* + * HPD might be set even if no monitor is connected, so also check that + * the link training was successful. + */ + if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, AST_IO_VGACRDC_LINK_SUCCESS)) + return false; return true; } -- cgit v1.2.3-59-g8ed1b From 55d4b69861e853ac987f6d593b44a3c18b468576 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 28 Jan 2025 17:32:48 -0500 Subject: Revert "drm/xe/lnl: Enable GuC SLPC DCC task" This reverts commit 50554bf3e56dd0c78ef1eedb685d0ab36c9c9987. DCC in LNL should be disabled. It was a mistake to decide to go against GuC platform defaults in this case and this could lead to regressions in some TDP limited scenarios instead of helping. Cc: Vinay Belgaumkar Cc: Jonathan Cavitt Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20250128223248.660748-1-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc_pc.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index 44b5211066ef..43f9617baba2 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -993,27 +993,6 @@ out: return ret; } -static int slpc_enable_dcc(struct xe_guc_pc *pc) -{ - int ret; - - ret = pc_action_set_param(pc, SLPC_PARAM_TASK_ENABLE_DCC, 1); - if (ret) - return ret; - - return pc_action_set_param(pc, SLPC_PARAM_TASK_DISABLE_DCC, 0); -} - -static int slpc_set_policies(struct xe_guc_pc *pc) -{ - struct xe_device *xe = pc_to_xe(pc); - - if (xe->info.platform == XE_LUNARLAKE) - return slpc_enable_dcc(pc); - - return 0; -} - /** * xe_guc_pc_start - Start GuC's Power Conservation component * @pc: Xe_GuC_PC instance @@ -1058,10 +1037,6 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) goto out; } - ret = slpc_set_policies(pc); - if (ret) - goto out; - ret = pc_init_freqs(pc); if (ret) goto out; -- cgit v1.2.3-59-g8ed1b From 5bea40687c5cf2a33bf04e9110eb2e2b80222ef5 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 14 Jan 2025 16:13:34 -0800 Subject: drm/i915/guc: Debug print LRC state entries only if the context is pinned After the context is unpinned the backing memory can also be unpinned, so any accesses via the lrc_reg_state pointer can end up in unmapped memory. To avoid that, make sure to only access that memory if the context is pinned when printing its info. v2: fix newline alignment Fixes: 28ff6520a34d ("drm/i915/guc: Update GuC debugfs to support new GuC") Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Cc: Matthew Brost Cc: # v5.15+ Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250115001334.3875347-1-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 9be6764d3cd3..85b847bb4e31 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -5535,12 +5535,20 @@ static inline void guc_log_context(struct drm_printer *p, { drm_printf(p, "GuC lrc descriptor %u:\n", ce->guc_id.id); drm_printf(p, "\tHW Context Desc: 0x%08x\n", ce->lrc.lrca); - drm_printf(p, "\t\tLRC Head: Internal %u, Memory %u\n", - ce->ring->head, - ce->lrc_reg_state[CTX_RING_HEAD]); - drm_printf(p, "\t\tLRC Tail: Internal %u, Memory %u\n", - ce->ring->tail, - ce->lrc_reg_state[CTX_RING_TAIL]); + if (intel_context_pin_if_active(ce)) { + drm_printf(p, "\t\tLRC Head: Internal %u, Memory %u\n", + ce->ring->head, + ce->lrc_reg_state[CTX_RING_HEAD]); + drm_printf(p, "\t\tLRC Tail: Internal %u, Memory %u\n", + ce->ring->tail, + ce->lrc_reg_state[CTX_RING_TAIL]); + intel_context_unpin(ce); + } else { + drm_printf(p, "\t\tLRC Head: Internal %u, Memory not pinned\n", + ce->ring->head); + drm_printf(p, "\t\tLRC Tail: Internal %u, Memory not pinned\n", + ce->ring->tail); + } drm_printf(p, "\t\tContext Pin Count: %u\n", atomic_read(&ce->pin_count)); drm_printf(p, "\t\tGuC ID Ref Count: %u\n", -- cgit v1.2.3-59-g8ed1b From 7748289df510638ba61fed86b59ce7d2fb4a194c Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 28 Jan 2025 07:42:42 -0800 Subject: drm/xe/guc: Fix size_t print format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use %zx format to print size_t to remove the following warning when building for i386: >> drivers/gpu/drm/xe/xe_guc_ct.c:1727:43: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat] 1727 | drm_printf(p, "[CTB].length: 0x%lx\n", snapshot->ctb_size); | ~~~ ^~~~~~~~~~~~~~~~~~ | %zx Cc: José Roberto de Souza Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501281627.H6nj184e-lkp@intel.com/ Fixes: cb1f868ca137 ("drm/xe: Make GUC binaries dump consistent with other binaries in devcoredump") Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250128154242.3371687-1-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_guc_ct.c | 2 +- drivers/gpu/drm/xe/xe_guc_log.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 497036675a38..72ad576fc18e 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -1724,7 +1724,7 @@ void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, snapshot->g2h_outstanding); if (snapshot->ctb) { - drm_printf(p, "[CTB].length: 0x%lx\n", snapshot->ctb_size); + drm_printf(p, "[CTB].length: 0x%zx\n", snapshot->ctb_size); xe_print_blob_ascii85(p, "[CTB].data", '\n', snapshot->ctb, 0, snapshot->ctb_size); } diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c index ab97ac728d7a..80514a446ba2 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.c +++ b/drivers/gpu/drm/xe/xe_guc_log.c @@ -204,7 +204,7 @@ void xe_guc_log_snapshot_print(struct xe_guc_log_snapshot *snapshot, struct drm_ drm_printf(p, "GuC timestamp: 0x%08llX [%llu]\n", snapshot->stamp, snapshot->stamp); drm_printf(p, "Log level: %u\n", snapshot->level); - drm_printf(p, "[LOG].length: 0x%lx\n", snapshot->size); + drm_printf(p, "[LOG].length: 0x%zx\n", snapshot->size); remain = snapshot->size; for (i = 0; i < snapshot->num_chunks; i++) { size_t size = min(GUC_LOG_CHUNK_SIZE, remain); -- cgit v1.2.3-59-g8ed1b From 8f6ddb4ab5db955bc826481d2f5c145aa5802ec1 Mon Sep 17 00:00:00 2001 From: Francois Dugast Date: Wed, 29 Jan 2025 18:52:41 +0100 Subject: drm/xe/gt_pagefault: Print engine class string The engine class index which is printed here is an internal representation for debugging. It is _not_ an index based on DRM_XE_ENGINE_CLASS_* values provided in the uAPI. Add the string representation of the engine class to the output in order to limit possible confusion by users when analyzing the logs. Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250129175241.338043-1-francois.dugast@intel.com Signed-off-by: Francois Dugast --- drivers/gpu/drm/xe/xe_gt_pagefault.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index 79c426dc2505..39344aeab112 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -264,12 +264,13 @@ static void print_pagefault(struct xe_device *xe, struct pagefault *pf) "\tFaultType: %d\n" "\tAccessType: %d\n" "\tFaultLevel: %d\n" - "\tEngineClass: %d\n" + "\tEngineClass: %d %s\n" "\tEngineInstance: %d\n", pf->asid, pf->vfid, pf->pdata, upper_32_bits(pf->page_addr), lower_32_bits(pf->page_addr), pf->fault_type, pf->access_type, pf->fault_level, - pf->engine_class, pf->engine_instance); + pf->engine_class, xe_hw_engine_class_to_str(pf->engine_class), + pf->engine_instance); } #define PF_MSG_LEN_DW 4 -- cgit v1.2.3-59-g8ed1b From 9069b783cd42963ecb47f7a614b663b4d257a5a7 Mon Sep 17 00:00:00 2001 From: Sebastian Brzezinka Date: Thu, 23 Jan 2025 14:38:40 +0000 Subject: Revert "drm/i915/gt: Log reason for setting TAINT_WARN at reset" This reverts commit 835443da6f50d9516b58bba5a4fdf9e563d961c7. Logging with gt_err() causes CI to detect an error even in cases of intentional error injection. Since real errors are already correctly reported by CI, this additional message is unnecessary. Furthermore, a GT wedge is already being logged elsewhere, so instead of adjusting the log level, revert the above mentioned commit to prevent redundant error reporting. Signed-off-by: Sebastian Brzezinka Reviewed-by: Krzysztof Karas Reviewed-by: Krzysztof Niemiec Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/pynwwza2xyvicokflxc6lduwwrzwoihihaan54ago3m2xzzagu@qva2ue4tydie --- drivers/gpu/drm/i915/gt/intel_reset.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 9e7c4879245e..76810ebb5e83 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1113,7 +1113,6 @@ static bool __intel_gt_unset_wedged(struct intel_gt *gt) * Warn CI about the unrecoverable wedged condition. * Time for a reboot. */ - gt_err(gt, "Unrecoverable wedged condition\n"); add_taint_for_CI(gt->i915, TAINT_WARN); return false; } @@ -1264,10 +1263,8 @@ void intel_gt_reset(struct intel_gt *gt, } ret = resume(gt); - if (ret) { - gt_err(gt, "Failed to resume (%d)\n", ret); + if (ret) goto taint; - } finish: reset_finish(gt, awake); @@ -1610,7 +1607,6 @@ void intel_gt_set_wedged_on_init(struct intel_gt *gt) set_bit(I915_WEDGED_ON_INIT, >->reset.flags); /* Wedged on init is non-recoverable */ - gt_err(gt, "Non-recoverable wedged on init\n"); add_taint_for_CI(gt->i915, TAINT_WARN); } -- cgit v1.2.3-59-g8ed1b From 2dbbbc1740388a8bc4a8237de0b009eecec8f998 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 30 Jan 2025 10:46:04 +0530 Subject: drm/i915/vrr: Add crtc_state dump for vrr.vsync params Add crtc_state dump for vrr.vsync_{start/end} params to track the state correctly. --v2: - remove vrr_ pretext and use space instead of underscore (Jani). --v3: - Rebase to latest drm-tip. Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250130051609.1796524-2-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 1fbaa67e2fea..36076e8d639b 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -292,10 +292,11 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, pipe_config->hw.adjusted_mode.crtc_vdisplay, pipe_config->framestart_delay, pipe_config->msa_timing_delay); - drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, flipline: %d, pipeline full: %d, guardband: %d\n", + drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, flipline: %d, pipeline full: %d, guardband: %d vsync start: %d, vsync end: %d\n", str_yes_no(pipe_config->vrr.enable), pipe_config->vrr.vmin, pipe_config->vrr.vmax, pipe_config->vrr.flipline, - pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband); + pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband, + pipe_config->vrr.vsync_start, pipe_config->vrr.vsync_end); drm_printf(&p, "vrr: vmin vblank: %d, vmax vblank: %d, vmin vtotal: %d, vmax vtotal: %d\n", intel_vrr_vmin_vblank_start(pipe_config), intel_vrr_vmax_vblank_start(pipe_config), -- cgit v1.2.3-59-g8ed1b From 387f269e56eafa461a314a30b4e7f85625b2cba6 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 30 Jan 2025 10:46:05 +0530 Subject: drm/i915/vrr: Compute vrr.vsync_{start, end} during full modeset vrr.vsync_{start,end} computation should not depend on crtc_state->vrr.enable. --v1: - Explain commit message more clearly [Jani] - Instead of tweaking to fastset use vrr.flipline while computing AS_SDP. --v2: - Correct computation of vrr.vsync_start/end should not depend on vrr.enable.[ville] - vrr enable disable requirement should not obstruct by SDP enable disable requirements. [Ville] --v3: - Create separate patch for crtc_state_dump [Ankit]. --v4: - Update commit message and header [Ankit]. Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250130051609.1796524-3-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_vrr.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index b268a0a01cd1..adb51609d0a3 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -299,7 +299,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } - if (intel_dp->as_sdp_supported && crtc_state->vrr.enable) { + if (HAS_AS_SDP(display)) { crtc_state->vrr.vsync_start = (crtc_state->hw.adjusted_mode.crtc_vtotal - crtc_state->hw.adjusted_mode.vsync_start); @@ -388,6 +388,12 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state) trans_vrr_ctl(crtc_state)); intel_de_write(display, TRANS_VRR_FLIPLINE(display, cpu_transcoder), crtc_state->vrr.flipline - 1); + + if (HAS_AS_SDP(display)) + intel_de_write(display, + TRANS_VRR_VSYNC(display, cpu_transcoder), + VRR_VSYNC_END(crtc_state->vrr.vsync_end) | + VRR_VSYNC_START(crtc_state->vrr.vsync_start)); } void intel_vrr_send_push(struct intel_dsb *dsb, @@ -432,12 +438,6 @@ void intel_vrr_enable(const struct intel_crtc_state *crtc_state) intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), TRANS_PUSH_EN); - if (HAS_AS_SDP(display)) - intel_de_write(display, - TRANS_VRR_VSYNC(display, cpu_transcoder), - VRR_VSYNC_END(crtc_state->vrr.vsync_end) | - VRR_VSYNC_START(crtc_state->vrr.vsync_start)); - if (crtc_state->cmrr.enable) { intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), VRR_CTL_VRR_ENABLE | VRR_CTL_CMRR_ENABLE | @@ -462,10 +462,6 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) TRANS_VRR_STATUS(display, cpu_transcoder), VRR_STATUS_VRR_EN_LIVE, 1000); intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 0); - - if (HAS_AS_SDP(display)) - intel_de_write(display, - TRANS_VRR_VSYNC(display, cpu_transcoder), 0); } void intel_vrr_get_config(struct intel_crtc_state *crtc_state) @@ -505,10 +501,6 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) TRANS_VRR_VMAX(display, cpu_transcoder)) + 1; crtc_state->vrr.vmin = intel_de_read(display, TRANS_VRR_VMIN(display, cpu_transcoder)) + 1; - } - - if (crtc_state->vrr.enable) { - crtc_state->mode_flags |= I915_MODE_FLAG_VRR; if (HAS_AS_SDP(display)) { trans_vrr_vsync = @@ -520,4 +512,7 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) REG_FIELD_GET(VRR_VSYNC_END_MASK, trans_vrr_vsync); } } + + if (crtc_state->vrr.enable) + crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } -- cgit v1.2.3-59-g8ed1b From c5806862543ff6c2ad242409fcdf0667eac26dae Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Thu, 30 Jan 2025 10:46:06 +0530 Subject: drm/i915/dp: fix the Adaptive sync Operation mode for SDP Currently we support Adaptive sync operation mode with dynamic frame rate, but instead the operation mode with fixed rate is set. This was initially set correctly in the earlier version of changes but later got changed, while defining a macro for the same. Fixes: a5bd5991cb8a ("drm/i915/display: Compute AS SDP parameters") Cc: Mitul Golani Cc: Ankit Nautiyal Cc: Jani Nikula Reviewed-by: Mitul Golani Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250130051609.1796524-4-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c239008658a8..0aeb2d188d80 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2831,7 +2831,6 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); - /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */ as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; as_sdp->length = 0x9; as_sdp->duration_incr_ms = 0; @@ -2842,7 +2841,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode); as_sdp->target_rr_divider = true; } else { - as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL; + as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL; as_sdp->vtotal = adjusted_mode->vtotal; as_sdp->target_rr = 0; } -- cgit v1.2.3-59-g8ed1b From 6218bd2e649ab3bcd097d7903dd4b93baa21c73d Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 30 Jan 2025 10:46:07 +0530 Subject: drm/i915/dp: Compute as_sdp.vtotal based on vrr timings Compute as_sdp.vtotal based on minimum vtotal calculated during vrr computation. --v2: - make a separate patch and update to vmin only [Ankit]. --v3: - Update vtotal to vmin for cmrr case as well [Ankit]. --v4: - update vtotal with wrapper function of vmin [Ville] Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250130051609.1796524-5-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0aeb2d188d80..c9ddf6eb2b25 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2834,15 +2834,14 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; as_sdp->length = 0x9; as_sdp->duration_incr_ms = 0; + as_sdp->vtotal = intel_vrr_vmin_vtotal(crtc_state); if (crtc_state->cmrr.enable) { as_sdp->mode = DP_AS_SDP_FAVT_TRR_REACHED; - as_sdp->vtotal = adjusted_mode->vtotal; as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode); as_sdp->target_rr_divider = true; } else { as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL; - as_sdp->vtotal = adjusted_mode->vtotal; as_sdp->target_rr = 0; } } -- cgit v1.2.3-59-g8ed1b From 08277aa5d5a44befd71717de35b956f55e1e8401 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 30 Jan 2025 10:46:08 +0530 Subject: drm/i915/dp: Compute as_sdp based on if vrr possible Adaptive sync sdp param computation, we can configure during full modeset as well when sink is having vrr support, where it doesn't need dependency on vrr.enable status and can also match vrr enable/disable fastset requirement. --v2: - Separate the change from as_sdp.vtotal. [Ankit] Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250130051609.1796524-6-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c9ddf6eb2b25..dac56fd17a21 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2826,7 +2826,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - if (!crtc_state->vrr.enable || !intel_dp->as_sdp_supported) + if (!intel_vrr_possible(crtc_state) || !intel_dp->as_sdp_supported) return; crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); -- cgit v1.2.3-59-g8ed1b From e9bb15cdf5c40996bd7b17ecb69fb317629b8efc Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 30 Jan 2025 10:46:09 +0530 Subject: drm/i915/display: Move as sdp params change to fastset as_sdp param changes from vrr to cmrr should happen to fastset. Changing as_sdp params should not trigger any modeset. Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250130051609.1796524-7-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7d68d652c1bc..60867b5b03ec 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5752,10 +5752,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_INFOFRAME(avi); PIPE_CONF_CHECK_INFOFRAME(spd); PIPE_CONF_CHECK_INFOFRAME(hdmi); - if (!fastset) + if (!fastset) { PIPE_CONF_CHECK_INFOFRAME(drm); + PIPE_CONF_CHECK_DP_AS_SDP(as_sdp); + } PIPE_CONF_CHECK_DP_VSC_SDP(vsc); - PIPE_CONF_CHECK_DP_AS_SDP(as_sdp); PIPE_CONF_CHECK_X(sync_mode_slaves_mask); PIPE_CONF_CHECK_I(master_transcoder); -- cgit v1.2.3-59-g8ed1b From 21ccac0e22aaf27b767f9de4bf573e7c47f619c8 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 29 Jan 2025 20:59:46 +0100 Subject: drm/xe/pf: Don't send BEGIN_ID if VF has no context/doorbells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turned out that GuC validates VF configuration immediately after receiving "some" set of configuration KLVs and complains if one of the critical, from GuC understanding, resource is left unprovisioned, even if PF should be still allowed to make late VF config adjustments, since VF was not yet started. This issue was discovered after we decided to asynchronously re-send configuration KLVs after GT reset/resume, as then fair VF auto-provisioning could already allocate some of the resources, which was a prerequiste for sending those config KLVs: # fair GGTT provisioning [] xe 0000:00:02.0: [drm] GT0: PF: pushed VF1 config with 2 KLVs: [] xe 0000:00:02.0: [drm] GT0: { key 0x0001 : 64b value 0x176a000 } # ggtt_start [] xe 0000:00:02.0: [drm] GT0: { key 0x0002 : 64b value 0xfd696000 } # ggtt_size [] xe 0000:00:02.0: [drm] GT0: PF: VF1 provisioned with 4251541504 (3.96 GiB) GGTT # re-provisioning worker [] xe 0000:00:02.0: [drm] *ERROR* GT0: H2G request 0x5503 failed: error 0x60 hint 0x0 [] xe 0000:00:02.0: [drm] GT0: PF: Failed to push VF1 14 config KLVs (-EIO) [] xe 0000:00:02.0: [drm] GT0: { key 0x0001 : 64b value 0x176a000 } # ggtt_start [] xe 0000:00:02.0: [drm] GT0: { key 0x0002 : 64b value 0xfd696000 } # ggtt_size [] xe 0000:00:02.0: [drm] GT0: { key 0x8a0b : 32b value 0 } # begin_ctx_id [] xe 0000:00:02.0: [drm] GT0: { key 0x0004 : 32b value 0 } # num_contexts [] xe 0000:00:02.0: [drm] GT0: { key 0x8a0a : 32b value 0 } # begin_db_id [] xe 0000:00:02.0: [drm] GT0: { key 0x0006 : 32b value 0 } # num_doorbells [] xe 0000:00:02.0: [drm] GT0: { key 0x8a01 : 32b value 0 } # exec_quantum [] xe 0000:00:02.0: [drm] GT0: { key 0x8a02 : 32b value 0 } # preempt_timeout [] xe 0000:00:02.0: [drm] GT0: { key 0x8a03 : 32b value 0 } # cat_error_count [] xe 0000:00:02.0: [drm] GT0: { key 0x8a04 : 32b value 0 } # engine_reset_count [] xe 0000:00:02.0: [drm] GT0: { key 0x8a05 : 32b value 0 } # page_fault_count [] xe 0000:00:02.0: [drm] GT0: { key 0x8a06 : 32b value 0 } # guc_time_us [] xe 0000:00:02.0: [drm] GT0: { key 0x8a07 : 32b value 0 } # irq_time_us [] xe 0000:00:02.0: [drm] GT0: { key 0x8a08 : 32b value 0 } # doorbell_time_us [] xe 0000:00:02.0: [drm] GT0: PF: Failed to push VF1 configuration (-EIO) To avoid such errors stop sending BEGIN_CONTEXT/DOORBELL_ID KLVs if no GuC context/doorbell IDs were provisioned to VF. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4176 Signed-off-by: Michal Wajdeczko Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20250129195947.764-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 9db1c920219d..c219c55f23ab 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -264,7 +264,7 @@ static u32 encode_config(u32 *cfg, const struct xe_gt_sriov_config *config, bool n += encode_config_ggtt(cfg, config, details); - if (details) { + if (details && config->num_ctxs) { cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_BEGIN_CONTEXT_ID); cfg[n++] = config->begin_ctx; } @@ -272,7 +272,7 @@ static u32 encode_config(u32 *cfg, const struct xe_gt_sriov_config *config, bool cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_NUM_CONTEXTS); cfg[n++] = config->num_ctxs; - if (details) { + if (details && config->num_dbs) { cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_BEGIN_DOORBELL_ID); cfg[n++] = config->begin_db; } -- cgit v1.2.3-59-g8ed1b From 33f17e2cbd930a2a00eb007d9b241b6db010a880 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 29 Jan 2025 20:59:47 +0100 Subject: drm/xe/pf: Reset GuC VF config when unprovisioning critical resource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GuC firmware counts received VF configuration KLVs and may start validation of the complete VF config even if some resources where unprovisioned in the meantime, leading to unexpected errors like: $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota tee: '/sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota': Input/output error To mitigate this problem trigger explicit VF config reset after unprovisioning any of the critical resources (GGTT, context or doorbell IDs) that GuC is monitoring. Signed-off-by: Michal Wajdeczko Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20250129195947.764-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 37 ++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index c219c55f23ab..b1d994d65589 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -338,6 +338,26 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) return err; } +static int pf_push_vf_cfg(struct xe_gt *gt, unsigned int vfid, bool reset) +{ + int err = 0; + + xe_gt_assert(gt, vfid); + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + if (reset) + err = pf_send_vf_cfg_reset(gt, vfid); + if (!err) + err = pf_push_full_vf_config(gt, vfid); + + return err; +} + +static int pf_refresh_vf_cfg(struct xe_gt *gt, unsigned int vfid) +{ + return pf_push_vf_cfg(gt, vfid, true); +} + static u64 pf_get_ggtt_alignment(struct xe_gt *gt) { struct xe_device *xe = gt_to_xe(gt); @@ -434,6 +454,10 @@ static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size) return err; pf_release_vf_config_ggtt(gt, config); + + err = pf_refresh_vf_cfg(gt, vfid); + if (unlikely(err)) + return err; } xe_gt_assert(gt, !xe_ggtt_node_allocated(config->ggtt_region)); @@ -759,6 +783,10 @@ static int pf_provision_vf_ctxs(struct xe_gt *gt, unsigned int vfid, u32 num_ctx return ret; pf_release_config_ctxs(gt, config); + + ret = pf_refresh_vf_cfg(gt, vfid); + if (unlikely(ret)) + return ret; } if (!num_ctxs) @@ -1056,6 +1084,10 @@ static int pf_provision_vf_dbs(struct xe_gt *gt, unsigned int vfid, u32 num_dbs) return ret; pf_release_config_dbs(gt, config); + + ret = pf_refresh_vf_cfg(gt, vfid); + if (unlikely(ret)) + return ret; } if (!num_dbs) @@ -2087,10 +2119,7 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh xe_gt_assert(gt, vfid); mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); - if (refresh) - err = pf_send_vf_cfg_reset(gt, vfid); - if (!err) - err = pf_push_full_vf_config(gt, vfid); + err = pf_push_vf_cfg(gt, vfid, refresh); mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); if (unlikely(err)) { -- cgit v1.2.3-59-g8ed1b From c13a42f2107c768715fbac518072363b57258e36 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Wed, 15 Jan 2025 11:08:04 -0300 Subject: drm/xe: Fix sort order of .o lists in Makefile The Makefile for xe asks us to keep the lists of object files sorted: # Please keep these build lists sorted! Reshuffle the lists into the correct sort order. That was done by filtering each unsorted list through 'LC_ALL=C sort'. Signed-off-by: Gustavo Sousa Reviewed-by: Lucas De Marchi Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250115140812.20799-1-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index ef900b9f0457..fdd3a0c9cb37 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -34,8 +34,8 @@ xe-y += xe_bb.o \ xe_dma_buf.o \ xe_drm_client.o \ xe_exec.o \ - xe_execlist.o \ xe_exec_queue.o \ + xe_execlist.o \ xe_force_wake.o \ xe_ggtt.o \ xe_gpu_scheduler.o \ @@ -67,11 +67,11 @@ xe-y += xe_bb.o \ xe_guc_pc.o \ xe_guc_submit.o \ xe_heci_gsc.o \ + xe_huc.o \ xe_hw_engine.o \ xe_hw_engine_class_sysfs.o \ xe_hw_engine_group.o \ xe_hw_fence.o \ - xe_huc.o \ xe_irq.o \ xe_lrc.o \ xe_migrate.o \ @@ -91,8 +91,8 @@ xe-y += xe_bb.o \ xe_range_fence.o \ xe_reg_sr.o \ xe_reg_whitelist.o \ - xe_rtp.o \ xe_ring_ops.o \ + xe_rtp.o \ xe_sa.o \ xe_sched_job.o \ xe_step.o \ @@ -104,8 +104,8 @@ xe-y += xe_bb.o \ xe_trace_bo.o \ xe_trace_guc.o \ xe_trace_lrc.o \ - xe_ttm_sys_mgr.o \ xe_ttm_stolen_mgr.o \ + xe_ttm_sys_mgr.o \ xe_ttm_vram_mgr.o \ xe_tuning.o \ xe_uc.o \ @@ -114,8 +114,8 @@ xe-y += xe_bb.o \ xe_vram.o \ xe_vram_freq.o \ xe_vsec.o \ - xe_wait_user_fence.o \ xe_wa.o \ + xe_wait_user_fence.o \ xe_wopcm.o xe-$(CONFIG_HMM_MIRROR) += xe_hmm.o @@ -224,6 +224,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_display_wa.o \ i915-display/intel_dkl_phy.o \ i915-display/intel_dmc.o \ + i915-display/intel_dmc_wl.o \ i915-display/intel_dp.o \ i915-display/intel_dp_aux.o \ i915-display/intel_dp_aux_backlight.o \ @@ -271,7 +272,6 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_vdsc.o \ i915-display/intel_vga.o \ i915-display/intel_vrr.o \ - i915-display/intel_dmc_wl.o \ i915-display/intel_wm.o \ i915-display/skl_scaler.o \ i915-display/skl_universal_plane.o \ -- cgit v1.2.3-59-g8ed1b From b73aebc7a1e0fd9d2a9d8ab7b88ada58bd80bb9f Mon Sep 17 00:00:00 2001 From: Jakub Kolakowski Date: Tue, 28 Jan 2025 11:03:00 +0000 Subject: drm/xe/pf: Add runtime registers for graphics gen >= 30 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing runtime registers for graphics versions of 3000 or higher. This is required for Xe3 where additionally we have MIRROR_L3BANK_ENABLE register. Signed-off-by: Jakub Kolakowski Suggested-by: Piotr Piórkowski Cc: Adam Miszczak Cc: Jakub Kolakowski Cc: Lukasz Laguna Cc: Marcin Bernatowicz Cc: Michal Wajdeczko Cc: Piotr Piorkowski Cc: Satyanarayana K V P Reviewed-by: Satyanarayana K V P Tested-by: Marcin Bernatowicz Signed-off-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20250128110300.2840596-2-jakub1.kolakowski@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c index 924e75b94aec..6b5f849a0722 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c @@ -176,11 +176,32 @@ static const struct xe_reg ver_2000_runtime_regs[] = { TIMESTAMP_OVERRIDE, /* _MMIO(0x44074) */ }; +static const struct xe_reg ver_3000_runtime_regs[] = { + RPM_CONFIG0, /* _MMIO(0x0d00) */ + XEHP_FUSE4, /* _MMIO(0x9114) */ + MIRROR_FUSE3, /* _MMIO(0x9118) */ + MIRROR_FUSE1, /* _MMIO(0x911c) */ + MIRROR_L3BANK_ENABLE, /* _MMIO(0x9130) */ + XELP_EU_ENABLE, /* _MMIO(0x9134) */ + XELP_GT_GEOMETRY_DSS_ENABLE, /* _MMIO(0x913c) */ + GT_VEBOX_VDBOX_DISABLE, /* _MMIO(0x9140) */ + XEHP_GT_COMPUTE_DSS_ENABLE, /* _MMIO(0x9144) */ + XEHPC_GT_COMPUTE_DSS_ENABLE_EXT,/* _MMIO(0x9148) */ + XE2_GT_COMPUTE_DSS_2, /* _MMIO(0x914c) */ + XE2_GT_GEOMETRY_DSS_1, /* _MMIO(0x9150) */ + XE2_GT_GEOMETRY_DSS_2, /* _MMIO(0x9154) */ + CTC_MODE, /* _MMIO(0xa26c) */ + HUC_KERNEL_LOAD_INFO, /* _MMIO(0xc1dc) */ +}; + static const struct xe_reg *pick_runtime_regs(struct xe_device *xe, unsigned int *count) { const struct xe_reg *regs; - if (GRAPHICS_VERx100(xe) >= 2000) { + if (GRAPHICS_VERx100(xe) >= 3000) { + *count = ARRAY_SIZE(ver_3000_runtime_regs); + regs = ver_3000_runtime_regs; + } else if (GRAPHICS_VERx100(xe) >= 2000) { *count = ARRAY_SIZE(ver_2000_runtime_regs); regs = ver_2000_runtime_regs; } else if (GRAPHICS_VERx100(xe) >= 1270) { -- cgit v1.2.3-59-g8ed1b From 8486de873730683a4b04815aa707d2e4e1028792 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Jan 2025 16:46:33 +0200 Subject: drm/i915/dp: constify struct link_config_limits pointers The limits get passed around, but are only modified in a few places. Constify the pointers elsewhere so it's easier to follow where they can be modified. Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/6ab2f68eef7849aca18e82ad788e44e9f82b576e.1738161945.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 18 +++++++++--------- drivers/gpu/drm/i915/display/intel_dp.h | 2 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index dac56fd17a21..6b64ea775098 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1941,7 +1941,7 @@ static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_cloc static int dsc_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, - struct link_config_limits *limits, + const struct link_config_limits *limits, u16 compressed_bppx16, int timeslots) { @@ -2061,7 +2061,7 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp) static int icl_dsc_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, - struct link_config_limits *limits, + const struct link_config_limits *limits, int dsc_max_bpp, int dsc_min_bpp, int pipe_bpp, @@ -2104,7 +2104,7 @@ static int xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, const struct intel_connector *connector, struct intel_crtc_state *pipe_config, - struct link_config_limits *limits, + const struct link_config_limits *limits, int dsc_max_bpp, int dsc_min_bpp, int pipe_bpp, @@ -2153,7 +2153,7 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, const struct intel_connector *connector, struct intel_crtc_state *pipe_config, - struct link_config_limits *limits, + const struct link_config_limits *limits, int pipe_bpp, int timeslots) { @@ -2185,7 +2185,7 @@ int intel_dp_dsc_min_src_input_bpc(void) } static -bool is_dsc_pipe_bpp_sufficient(struct link_config_limits *limits, +bool is_dsc_pipe_bpp_sufficient(const struct link_config_limits *limits, int pipe_bpp) { return pipe_bpp >= limits->pipe.min_bpp && @@ -2194,7 +2194,7 @@ bool is_dsc_pipe_bpp_sufficient(struct link_config_limits *limits, static int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp, - struct link_config_limits *limits) + const struct link_config_limits *limits) { struct intel_display *display = to_intel_display(intel_dp); int forced_bpp; @@ -2220,7 +2220,7 @@ int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp, static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, - struct link_config_limits *limits, + const struct link_config_limits *limits, int timeslots) { const struct intel_connector *connector = @@ -2270,7 +2270,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, - struct link_config_limits *limits) + const struct link_config_limits *limits) { struct intel_display *display = to_intel_display(intel_dp); struct intel_connector *connector = @@ -2335,7 +2335,7 @@ static void intel_dp_fec_compute_config(struct intel_dp *intel_dp, int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, - struct link_config_limits *limits, + const struct link_config_limits *limits, int timeslots, bool compute_pipe_bpp) { diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index ca49f0a05da5..ffc27f8ad226 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -75,7 +75,7 @@ int intel_dp_compute_config(struct intel_encoder *encoder, int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, - struct link_config_limits *limits, + const struct link_config_limits *limits, int timeslots, bool recompute_pipe_bpp); void intel_dp_audio_compute_config(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 7c1de9aeeacc..1d5788babcff 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -363,7 +363,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, int max_bpp, int min_bpp, - struct link_config_limits *limits, + const struct link_config_limits *limits, struct drm_connector_state *conn_state, int step, bool dsc) { @@ -388,7 +388,7 @@ static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp, static int mst_stream_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, - struct link_config_limits *limits) + const struct link_config_limits *limits) { /* * FIXME: allocate the BW according to link_bpp, which in the case of @@ -404,7 +404,7 @@ static int mst_stream_compute_link_config(struct intel_dp *intel_dp, static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, - struct link_config_limits *limits) + const struct link_config_limits *limits) { struct intel_display *display = to_intel_display(intel_dp); struct intel_connector *connector = to_intel_connector(conn_state->connector); -- cgit v1.2.3-59-g8ed1b From bb322c6fa16f97951d75dba46b9ef0cb2cfcb2d5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Jan 2025 16:46:34 +0200 Subject: drm/i915/dp: change the order of intel_dp_mtp_tu_compute_config() params Pointers first, bpp params in min, max, step. This is slightly more natural to follow. Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/ea9669edc5973cdbca92aeb4e168850015e9d1bb.1738161945.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 8 +++----- drivers/gpu/drm/i915/display/intel_dp_mst.h | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6b64ea775098..4fe274105c1d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2643,9 +2643,9 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, if (!ret && intel_dp_is_uhbr(pipe_config)) ret = intel_dp_mtp_tu_compute_config(intel_dp, pipe_config, + conn_state, pipe_config->pipe_bpp, pipe_config->pipe_bpp, - conn_state, 0, false); if (ret) dsc_needed = true; diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 1d5788babcff..1cb2b8fac296 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -211,9 +211,8 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, - int max_bpp, int min_bpp, struct drm_connector_state *conn_state, - int step, bool dsc) + int min_bpp, int max_bpp, int step, bool dsc) { struct intel_display *display = to_intel_display(intel_dp); struct drm_atomic_state *state = crtc_state->uapi.state; @@ -380,9 +379,8 @@ static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp, mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock, crtc_state->lane_count); - return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, - max_bpp, min_bpp, - conn_state, step, dsc); + return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, + min_bpp, max_bpp, step, dsc); } static int mst_stream_compute_link_config(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h index c6bdc1d190a4..a713a1c10154 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.h +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h @@ -33,8 +33,7 @@ bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp); int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, - int max_bpp, int min_bpp, struct drm_connector_state *conn_state, - int step, bool dsc); + int min_bpp, int max_bpp, int step, bool dsc); #endif /* __INTEL_DP_MST_H__ */ -- cgit v1.2.3-59-g8ed1b From f3ee4d5b4392081427cd9c97432fbdfecfae26f5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Jan 2025 16:46:35 +0200 Subject: drm/i915/mst: change where lane_count and port_clock are set Semantically mst_stream_find_vcpi_slots_for_bpp() does not seem like the place to make decisions about lane_count and port_clock. Move them to the callers, and remove the limits parameter that becomes unused. This leads to slight duplication, but a) this makes further refactoring easier, and b) also the SST code sets link parameters in different places for uncompressed and compressed paths. Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/101ce3fc6afff55d966336f3ab72090317750f82.1738161945.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 1cb2b8fac296..6ba35f685282 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -362,7 +362,6 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, int max_bpp, int min_bpp, - const struct link_config_limits *limits, struct drm_connector_state *conn_state, int step, bool dsc) { @@ -373,9 +372,6 @@ static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp, 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; - mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock, crtc_state->lane_count); @@ -388,6 +384,9 @@ static int mst_stream_compute_link_config(struct intel_dp *intel_dp, struct drm_connector_state *conn_state, const struct link_config_limits *limits) { + crtc_state->lane_count = limits->max_lane_count; + crtc_state->port_clock = limits->max_rate; + /* * FIXME: allocate the BW according to link_bpp, which in the case of * YUV420 is only half of the pipe bpp value. @@ -395,7 +394,6 @@ static int mst_stream_compute_link_config(struct intel_dp *intel_dp, return mst_stream_find_vcpi_slots_for_bpp(intel_dp, crtc_state, fxp_q4_to_int(limits->link.max_bpp_x16), fxp_q4_to_int(limits->link.min_bpp_x16), - limits, conn_state, 2 * 3, false); } @@ -453,8 +451,11 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, min_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, min_compressed_bpp, crtc_state->pipe_bpp); + crtc_state->lane_count = limits->max_lane_count; + crtc_state->port_clock = limits->max_rate; + return mst_stream_find_vcpi_slots_for_bpp(intel_dp, crtc_state, max_compressed_bpp, - min_compressed_bpp, limits, + min_compressed_bpp, conn_state, 1, true); } -- cgit v1.2.3-59-g8ed1b From 8c271e4d1172a9ebce172aea15edfb222836c57a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Jan 2025 16:46:36 +0200 Subject: drm/i915/mst: handle mst pbn_div in intel_dp_mtp_tu_compute_config() Move mst_state->pbn_div calculation to intel_dp_mtp_tu_compute_config() to allow further refactoring. Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/0cc1b507601c9964ebae7d50b1f90b1ce00acb11.1738161945.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 31 +++++++++++++---------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 6ba35f685282..e596a7727070 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -216,15 +216,25 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, { struct intel_display *display = to_intel_display(intel_dp); struct drm_atomic_state *state = crtc_state->uapi.state; + struct drm_dp_mst_topology_state *mst_state = NULL; struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - fixed20_12 pbn_div; + bool is_mst = intel_dp->is_mst; int bpp, slots = -EINVAL; int dsc_slice_count = 0; int max_dpt_bpp; + if (is_mst) { + mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock, + crtc_state->lane_count); + } + if (dsc) { if (!intel_dp_supports_fec(intel_dp, connector, crtc_state)) return -EINVAL; @@ -232,9 +242,6 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, crtc_state->fec_enable = !intel_dp_is_uhbr(crtc_state); } - pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock, - crtc_state->lane_count); - max_dpt_bpp = intel_dp_mst_max_dpt_bpp(crtc_state, dsc); if (max_bpp > max_dpt_bpp) { drm_dbg_kms(display->drm, "Limiting bpp to max DPT bpp (%d -> %d)\n", @@ -270,7 +277,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, link_bpp_x16, &crtc_state->dp_m_n); - if (intel_dp->is_mst) { + if (is_mst) { int remote_bw_overhead; int remote_tu; fixed20_12 pbn; @@ -295,7 +302,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, pbn.full = dfixed_const(intel_dp_mst_calc_pbn(adjusted_mode->crtc_clock, link_bpp_x16, remote_bw_overhead)); - remote_tu = DIV_ROUND_UP(pbn.full, pbn_div.full); + remote_tu = DIV_ROUND_UP(pbn.full, mst_state->pbn_div.full); /* * Aligning the TUs ensures that symbols consisting of multiple @@ -313,7 +320,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, * allocated for the whole path and the TUs allocated for the * first branch device's link also applies here. */ - pbn.full = remote_tu * pbn_div.full; + pbn.full = remote_tu * mst_state->pbn_div.full; drm_WARN_ON(display->drm, remote_tu < crtc_state->dp_m_n.tu); crtc_state->dp_m_n.tu = remote_tu; @@ -365,16 +372,6 @@ static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp, struct drm_connector_state *conn_state, int step, bool dsc) { - struct drm_atomic_state *state = crtc_state->uapi.state; - struct drm_dp_mst_topology_state *mst_state; - - mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); - if (IS_ERR(mst_state)) - return PTR_ERR(mst_state); - - mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock, - crtc_state->lane_count); - return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, min_bpp, max_bpp, step, dsc); } -- cgit v1.2.3-59-g8ed1b From 6e2e27c20dcfc8229954001bbb206ab4ecdc27d5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Jan 2025 16:46:37 +0200 Subject: drm/i915/mst: remove unnecessary mst_stream_find_vcpi_slots_for_bpp() mst_stream_find_vcpi_slots_for_bpp() has become a thin wrapper that merely juggles parameters around. Remove it. Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/abdd205087dc2ab0bdae09d7374d5f262f605aba.1738161945.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index e596a7727070..825c52595921 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -366,16 +366,6 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, return 0; } -static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state, - int max_bpp, int min_bpp, - struct drm_connector_state *conn_state, - int step, bool dsc) -{ - return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, - min_bpp, max_bpp, step, dsc); -} - static int mst_stream_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, @@ -388,10 +378,10 @@ static int mst_stream_compute_link_config(struct intel_dp *intel_dp, * FIXME: allocate the BW according to link_bpp, which in the case of * YUV420 is only half of the pipe bpp value. */ - return mst_stream_find_vcpi_slots_for_bpp(intel_dp, crtc_state, - fxp_q4_to_int(limits->link.max_bpp_x16), - fxp_q4_to_int(limits->link.min_bpp_x16), - conn_state, 2 * 3, false); + return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, + fxp_q4_to_int(limits->link.min_bpp_x16), + fxp_q4_to_int(limits->link.max_bpp_x16), + 2 * 3, false); } static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, @@ -451,9 +441,8 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, crtc_state->lane_count = limits->max_lane_count; crtc_state->port_clock = limits->max_rate; - return mst_stream_find_vcpi_slots_for_bpp(intel_dp, crtc_state, max_compressed_bpp, - min_compressed_bpp, - conn_state, 1, true); + return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, + min_compressed_bpp, max_compressed_bpp, 1, true); } static int mst_stream_update_slots(struct intel_dp *intel_dp, -- cgit v1.2.3-59-g8ed1b From 31c726562849831b4c7f98d2fb267974b9390527 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Jan 2025 16:46:38 +0200 Subject: drm/i915/mst: use min_array() and max_array() instead of hand-rolling Improve code clarity by using existing min_array() and max_array() helpers to find the lowest and highest values in an array. Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/62a104535c01c667a99ec209c3218a13355568cf.1738161945.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 825c52595921..ed7640728b22 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -391,7 +391,7 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, { struct intel_display *display = to_intel_display(intel_dp); struct intel_connector *connector = to_intel_connector(conn_state->connector); - int i, num_bpc; + int num_bpc; u8 dsc_bpc[3] = {}; int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp; int min_compressed_bpp, max_compressed_bpp; @@ -405,15 +405,8 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, drm_dbg_kms(display->drm, "DSC Source supported min bpp %d max bpp %d\n", min_bpp, max_bpp); - sink_max_bpp = dsc_bpc[0] * 3; - sink_min_bpp = sink_max_bpp; - - for (i = 1; i < num_bpc; i++) { - if (sink_min_bpp > dsc_bpc[i] * 3) - sink_min_bpp = dsc_bpc[i] * 3; - if (sink_max_bpp < dsc_bpc[i] * 3) - sink_max_bpp = dsc_bpc[i] * 3; - } + sink_min_bpp = min_array(dsc_bpc, num_bpc) * 3; + sink_max_bpp = max_array(dsc_bpc, num_bpc) * 3; drm_dbg_kms(display->drm, "DSC Sink supported min bpp %d max bpp %d\n", sink_min_bpp, sink_max_bpp); -- cgit v1.2.3-59-g8ed1b From cf29a866a139519d6274756d65ebc29c9d749034 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 21 Jan 2025 15:28:48 +0100 Subject: drm/xe/display: Add intel_plane_initial_vblank_wait We're changing the driver to have no interrupts during early init for Xe, so we poll the PIPE_FRMSTMSMP counter instead. Interrupts cannot be enabled during FB readout because memirq's requires an allocation. This would overwrite the FB we want to read out. While it might be possible to also run do the same in i915 and run it without interrupts, the platforms i915 supports had a less clear distinction between display and graphics. For this reason I choose only to touch Xe for now. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250121142850.4960-1-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_display.c | 6 +++--- drivers/gpu/drm/i915/display/intel_plane_initial.c | 7 ++++++- drivers/gpu/drm/i915/display/intel_plane_initial.h | 2 ++ drivers/gpu/drm/xe/display/xe_plane_initial.c | 19 ++++++++++++++++++- 4 files changed, 29 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4271da219b41..6f6a535ea486 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -796,7 +796,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 && hsw_ips_disable(crtc_state)) { crtc_state->ips_enabled = false; - intel_crtc_wait_for_next_vblank(crtc); + intel_plane_initial_vblank_wait(crtc); } /* @@ -810,7 +810,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, */ if (HAS_GMCH(dev_priv) && intel_set_memory_cxsr(dev_priv, false)) - intel_crtc_wait_for_next_vblank(crtc); + intel_plane_initial_vblank_wait(crtc); /* * Gen2 reports pipe underruns whenever all planes are disabled. @@ -820,7 +820,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); intel_plane_disable_arm(NULL, plane, crtc_state); - intel_crtc_wait_for_next_vblank(crtc); + intel_plane_initial_vblank_wait(crtc); } unsigned int diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 6789b7f14095..b1675b46e06c 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -14,6 +14,11 @@ #include "intel_frontbuffer.h" #include "intel_plane_initial.h" +void intel_plane_initial_vblank_wait(struct intel_crtc *crtc) +{ + intel_crtc_wait_for_next_vblank(crtc); +} + static bool intel_reuse_initial_plane_obj(struct intel_crtc *this, const struct intel_initial_plane_config plane_configs[], @@ -442,7 +447,7 @@ void intel_initial_plane_config(struct intel_display *display) intel_find_initial_plane_obj(crtc, plane_configs); if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config)) - intel_crtc_wait_for_next_vblank(crtc); + intel_plane_initial_vblank_wait(crtc); plane_config_fini(plane_config); } diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.h b/drivers/gpu/drm/i915/display/intel_plane_initial.h index 6c6aa717ed21..5c315acda210 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.h +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.h @@ -6,8 +6,10 @@ #ifndef __INTEL_PLANE_INITIAL_H__ #define __INTEL_PLANE_INITIAL_H__ +struct intel_crtc; struct intel_display; void intel_initial_plane_config(struct intel_display *display); +void intel_plane_initial_vblank_wait(struct intel_crtc *crtc); #endif diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 2eb9633f163a..a22e7adfb09d 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -8,7 +8,9 @@ #include "regs/xe_gtt_defs.h" #include "xe_ggtt.h" +#include "xe_mmio.h" +#include "i915_reg.h" #include "intel_atomic_plane.h" #include "intel_crtc.h" #include "intel_display.h" @@ -22,6 +24,21 @@ #include +void intel_plane_initial_vblank_wait(struct intel_crtc *crtc) +{ + /* Early xe has no irq */ + struct xe_device *xe = to_xe_device(crtc->base.dev); + struct xe_reg pipe_frmtmstmp = XE_REG(i915_mmio_reg_offset(PIPE_FRMTMSTMP(crtc->pipe))); + u32 timestamp; + int ret; + + timestamp = xe_mmio_read32(xe_root_tile_mmio(xe), pipe_frmtmstmp); + + ret = xe_mmio_wait32_not(xe_root_tile_mmio(xe), pipe_frmtmstmp, ~0U, timestamp, 40000U, ×tamp, false); + if (ret < 0) + drm_warn(&xe->drm, "waiting for early vblank failed with %i\n", ret); +} + static bool intel_reuse_initial_plane_obj(struct intel_crtc *this, const struct intel_initial_plane_config plane_configs[], @@ -303,7 +320,7 @@ void intel_initial_plane_config(struct intel_display *display) intel_find_initial_plane_obj(crtc, plane_configs); if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config)) - intel_crtc_wait_for_next_vblank(crtc); + intel_plane_initial_vblank_wait(crtc); plane_config_fini(plane_config); } -- cgit v1.2.3-59-g8ed1b From f595fe5f6ae7d74d7352e2577ca1577704b64b3b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 21 Jan 2025 15:28:49 +0100 Subject: drm/xe: Defer irq init until after xe_display_init_noaccel As stated in previous commit, we have to move interrupt handling until after xe_display_init_noaccel, as using memirqs would require an allocation. A full solution will of course require memirq allocation to be moved, but the first part only focuses on the required changes to display. Reviewed-by: Ilia Levi Link: https://patchwork.freedesktop.org/patch/msgid/20250121142850.4960-2-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 8fedc72e9db4..4d401e4da70b 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -814,10 +814,6 @@ int xe_device_probe(struct xe_device *xe) if (err) return err; - err = xe_irq_install(xe); - if (err) - goto err; - err = probe_has_flat_ccs(xe); if (err) goto err; @@ -851,6 +847,10 @@ int xe_device_probe(struct xe_device *xe) goto err; } + err = xe_irq_install(xe); + if (err) + goto err; + for_each_gt(gt, xe, id) { last_gt = id; -- cgit v1.2.3-59-g8ed1b From 65e366ace5ee3637179658e8cf37f934c857f563 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 21 Jan 2025 15:28:50 +0100 Subject: drm/xe/display: Use a single early init call for display Now that interrupts are disabled for xe_display_init_noaccel, both xe_display_init_noirq and xe_display_init_noaccel run in the same context. This means that we can get rid of the 3 different init calls. Without interrupts, nothing is touching display up to this point. Unify those 3 early display calls into a single xe_display_init_early(), this makes the init sequence cleaner, and display less tangled during init. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250121142850.4960-3-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/display/xe_display.c | 73 +++++++++------------------------ drivers/gpu/drm/xe/display/xe_display.h | 8 +--- drivers/gpu/drm/xe/xe_device.c | 10 +---- 3 files changed, 22 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index b3921dbc52ff..7f0d8f00acff 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -101,19 +101,25 @@ int xe_display_create(struct xe_device *xe) return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); } -static void xe_display_fini_nommio(struct drm_device *dev, void *dummy) +static void xe_display_fini_early(void *arg) { - struct xe_device *xe = to_xe_device(dev); + struct xe_device *xe = arg; struct intel_display *display = &xe->display; if (!xe->info.probe_display) return; + intel_display_driver_remove_nogem(display); + intel_display_driver_remove_noirq(display); + intel_opregion_cleanup(display); intel_power_domains_cleanup(display); } -int xe_display_init_nommio(struct xe_device *xe) +int xe_display_init_early(struct xe_device *xe) { + struct intel_display *display = &xe->display; + int err; + if (!xe->info.probe_display) return 0; @@ -123,29 +129,6 @@ int xe_display_init_nommio(struct xe_device *xe) /* This must be called before any calls to HAS_PCH_* */ intel_detect_pch(xe); - return drmm_add_action_or_reset(&xe->drm, xe_display_fini_nommio, xe); -} - -static void xe_display_fini_noirq(void *arg) -{ - struct xe_device *xe = arg; - struct intel_display *display = &xe->display; - - if (!xe->info.probe_display) - return; - - intel_display_driver_remove_noirq(display); - intel_opregion_cleanup(display); -} - -int xe_display_init_noirq(struct xe_device *xe) -{ - struct intel_display *display = &xe->display; - int err; - - if (!xe->info.probe_display) - return 0; - intel_display_driver_early_probe(display); /* Early display init.. */ @@ -162,38 +145,20 @@ int xe_display_init_noirq(struct xe_device *xe) intel_display_device_info_runtime_init(display); err = intel_display_driver_probe_noirq(display); - if (err) { - intel_opregion_cleanup(display); - return err; - } - - return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noirq, xe); -} - -static void xe_display_fini_noaccel(void *arg) -{ - struct xe_device *xe = arg; - struct intel_display *display = &xe->display; - - if (!xe->info.probe_display) - return; - - intel_display_driver_remove_nogem(display); -} - -int xe_display_init_noaccel(struct xe_device *xe) -{ - struct intel_display *display = &xe->display; - int err; - - if (!xe->info.probe_display) - return 0; + if (err) + goto err_opregion; err = intel_display_driver_probe_nogem(display); if (err) - return err; + goto err_noirq; - return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noaccel, xe); + return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_early, xe); +err_noirq: + intel_display_driver_remove_noirq(display); + intel_power_domains_cleanup(display); +err_opregion: + intel_opregion_cleanup(display); + return err; } int xe_display_init(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index 233f81a26c25..e2a99624f706 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -20,9 +20,7 @@ int xe_display_create(struct xe_device *xe); int xe_display_probe(struct xe_device *xe); -int xe_display_init_nommio(struct xe_device *xe); -int xe_display_init_noirq(struct xe_device *xe); -int xe_display_init_noaccel(struct xe_device *xe); +int xe_display_init_early(struct xe_device *xe); int xe_display_init(struct xe_device *xe); void xe_display_fini(struct xe_device *xe); @@ -54,9 +52,7 @@ static inline int xe_display_create(struct xe_device *xe) { return 0; } static inline int xe_display_probe(struct xe_device *xe) { return 0; } -static inline int xe_display_init_nommio(struct xe_device *xe) { return 0; } -static inline int xe_display_init_noirq(struct xe_device *xe) { return 0; } -static inline int xe_display_init_noaccel(struct xe_device *xe) { return 0; } +static inline int xe_display_init_early(struct xe_device *xe) { return 0; } static inline int xe_display_init(struct xe_device *xe) { return 0; } static inline void xe_display_fini(struct xe_device *xe) {} diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 4d401e4da70b..8a2763e8a6e2 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -752,10 +752,6 @@ int xe_device_probe(struct xe_device *xe) return err; xe->info.mem_region_mask = 1; - err = xe_display_init_nommio(xe); - if (err) - return err; - err = xe_set_dma_info(xe); if (err) return err; @@ -810,10 +806,6 @@ int xe_device_probe(struct xe_device *xe) if (err) return err; - err = xe_display_init_noirq(xe); - if (err) - return err; - err = probe_has_flat_ccs(xe); if (err) goto err; @@ -837,7 +829,7 @@ int xe_device_probe(struct xe_device *xe) * This is the reason the first allocation needs to be done * inside display. */ - err = xe_display_init_noaccel(xe); + err = xe_display_init_early(xe); if (err) goto err; -- cgit v1.2.3-59-g8ed1b From d9bc304437da6b74ac2b6644fe47702b8286eb8d Mon Sep 17 00:00:00 2001 From: Riana Tauro Date: Fri, 31 Jan 2025 13:35:27 +0530 Subject: drm/xe: Skip survivability mode for VF Follow the probe flow in case of VF and do not enter survivability mode in case of pcode init failure. Fixes: 5e940312a2ac ("drm/xe: Add functions and sysfs for boot survivability") Suggested-by: Satyanarayana K V P Signed-off-by: Riana Tauro Reviewed-by: Satyanarayana K V P Link: https://patchwork.freedesktop.org/patch/msgid/20250131080527.2256475-1-riana.tauro@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_survivability_mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.c b/drivers/gpu/drm/xe/xe_survivability_mode.c index c619560af74f..02b4eadf8407 100644 --- a/drivers/gpu/drm/xe/xe_survivability_mode.c +++ b/drivers/gpu/drm/xe/xe_survivability_mode.c @@ -177,7 +177,7 @@ bool xe_survivability_mode_required(struct xe_device *xe) struct xe_mmio *mmio = xe_root_tile_mmio(xe); u32 data; - if (!IS_DGFX(xe) || xe->info.platform < XE_BATTLEMAGE) + if (!IS_DGFX(xe) || xe->info.platform < XE_BATTLEMAGE || IS_SRIOV_VF(xe)) return false; data = xe_mmio_read32(mmio, PCODE_SCRATCH(0)); -- cgit v1.2.3-59-g8ed1b From a67221b5eb8d59fb7e1f0df3ef9945b6a0f32cca Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 31 Jan 2025 09:43:42 +0530 Subject: drm/i915/dp: Return min bpc supported by source instead of 0 Currently, intel_dp_dsc_max_src_input_bpc can return 0 for platforms not supporting DSC, which could theoretically cause issues in clamp() due to a low limit being greater than the high limit. Instead, return the minimum bpc supported by the source to prevent such issues. Reported-by: Linux Kernel Functional Testing Closes: https://lore.kernel.org/all/CA+G9fYtNfM399_=_ff81zeRJv=0+z7oFJfPGmJgTp6yrJmU+1w@mail.gmail.com/ Fixes: 160672b86b0d ("drm/i915/dp: Use clamp for pipe_bpp limits with DSC") Cc: Suraj Kandpal Cc: Jani Nikula Cc: Rodrigo Vivi Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Tested-by: Chaitanya Kumar Borah Link: https://patchwork.freedesktop.org/patch/msgid/20250131041342.3086716-1-ankit.k.nautiyal@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4fe274105c1d..00aba97631a9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1791,7 +1791,7 @@ int intel_dp_dsc_max_src_input_bpc(struct intel_display *display) if (DISPLAY_VER(display) == 11) return 10; - return 0; + return intel_dp_dsc_min_src_input_bpc(); } int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector, -- cgit v1.2.3-59-g8ed1b From d07569ebcbd645e6afac7145b2daea11da5c6384 Mon Sep 17 00:00:00 2001 From: Matthew Leung Date: Fri, 17 Jan 2025 10:09:37 -0700 Subject: bus: mhi: host: Refactor BHI/BHIe based firmware loading Refactor the firmware loading code to have distinct helper functions for BHI and BHIe operations. This lays the foundation for separating the firmware loading protocol from the firmware being loaded and the EE it is loaded in. Signed-off-by: Matthew Leung Reviewed-by: Youssef Samir Reviewed-by: Jeffrey Hugo Signed-off-by: Jeffrey Hugo Reviewed-by: Manivannan Sadhasivam Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-2-quic_jhugo@quicinc.com --- drivers/bus/mhi/host/boot.c | 144 ++++++++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c index e8c92972f9df..9fe13d3f09f0 100644 --- a/drivers/bus/mhi/host/boot.c +++ b/drivers/bus/mhi/host/boot.c @@ -177,6 +177,36 @@ int mhi_download_rddm_image(struct mhi_controller *mhi_cntrl, bool in_panic) } EXPORT_SYMBOL_GPL(mhi_download_rddm_image); +static void mhi_fw_load_error_dump(struct mhi_controller *mhi_cntrl) +{ + struct device *dev = &mhi_cntrl->mhi_dev->dev; + rwlock_t *pm_lock = &mhi_cntrl->pm_lock; + void __iomem *base = mhi_cntrl->bhi; + int ret, i; + u32 val; + struct { + char *name; + u32 offset; + } error_reg[] = { + { "ERROR_CODE", BHI_ERRCODE }, + { "ERROR_DBG1", BHI_ERRDBG1 }, + { "ERROR_DBG2", BHI_ERRDBG2 }, + { "ERROR_DBG3", BHI_ERRDBG3 }, + { NULL }, + }; + + read_lock_bh(pm_lock); + if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { + for (i = 0; error_reg[i].name; i++) { + ret = mhi_read_reg(mhi_cntrl, base, error_reg[i].offset, &val); + if (ret) + break; + dev_err(dev, "Reg: %s value: 0x%x\n", error_reg[i].name, val); + } + } + read_unlock_bh(pm_lock); +} + static int mhi_fw_load_bhie(struct mhi_controller *mhi_cntrl, const struct mhi_buf *mhi_buf) { @@ -226,24 +256,13 @@ static int mhi_fw_load_bhie(struct mhi_controller *mhi_cntrl, } static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl, - dma_addr_t dma_addr, - size_t size) + const struct mhi_buf *mhi_buf) { - u32 tx_status, val, session_id; - int i, ret; - void __iomem *base = mhi_cntrl->bhi; - rwlock_t *pm_lock = &mhi_cntrl->pm_lock; struct device *dev = &mhi_cntrl->mhi_dev->dev; - struct { - char *name; - u32 offset; - } error_reg[] = { - { "ERROR_CODE", BHI_ERRCODE }, - { "ERROR_DBG1", BHI_ERRDBG1 }, - { "ERROR_DBG2", BHI_ERRDBG2 }, - { "ERROR_DBG3", BHI_ERRDBG3 }, - { NULL }, - }; + rwlock_t *pm_lock = &mhi_cntrl->pm_lock; + void __iomem *base = mhi_cntrl->bhi; + u32 tx_status, session_id; + int ret; read_lock_bh(pm_lock); if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { @@ -255,11 +274,9 @@ static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl, dev_dbg(dev, "Starting image download via BHI. Session ID: %u\n", session_id); mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, - upper_32_bits(dma_addr)); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, - lower_32_bits(dma_addr)); - mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size); + mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, upper_32_bits(mhi_buf->dma_addr)); + mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, lower_32_bits(mhi_buf->dma_addr)); + mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, mhi_buf->len); mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, session_id); read_unlock_bh(pm_lock); @@ -274,18 +291,7 @@ static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl, if (tx_status == BHI_STATUS_ERROR) { dev_err(dev, "Image transfer failed\n"); - read_lock_bh(pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - for (i = 0; error_reg[i].name; i++) { - ret = mhi_read_reg(mhi_cntrl, base, - error_reg[i].offset, &val); - if (ret) - break; - dev_err(dev, "Reg: %s value: 0x%x\n", - error_reg[i].name, val); - } - } - read_unlock_bh(pm_lock); + mhi_fw_load_error_dump(mhi_cntrl); goto invalid_pm_state; } @@ -296,6 +302,16 @@ invalid_pm_state: return -EIO; } +static void mhi_free_bhi_buffer(struct mhi_controller *mhi_cntrl, + struct image_info *image_info) +{ + struct mhi_buf *mhi_buf = image_info->mhi_buf; + + dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr); + kfree(image_info->mhi_buf); + kfree(image_info); +} + void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, struct image_info *image_info) { @@ -310,6 +326,45 @@ void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, kfree(image_info); } +static int mhi_alloc_bhi_buffer(struct mhi_controller *mhi_cntrl, + struct image_info **image_info, + size_t alloc_size) +{ + struct image_info *img_info; + struct mhi_buf *mhi_buf; + + img_info = kzalloc(sizeof(*img_info), GFP_KERNEL); + if (!img_info) + return -ENOMEM; + + /* Allocate memory for entry */ + img_info->mhi_buf = kzalloc(sizeof(*img_info->mhi_buf), GFP_KERNEL); + if (!img_info->mhi_buf) + goto error_alloc_mhi_buf; + + /* Allocate and populate vector table */ + mhi_buf = img_info->mhi_buf; + + mhi_buf->len = alloc_size; + mhi_buf->buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, + &mhi_buf->dma_addr, GFP_KERNEL); + if (!mhi_buf->buf) + goto error_alloc_segment; + + img_info->bhi_vec = NULL; + img_info->entries = 1; + *image_info = img_info; + + return 0; + +error_alloc_segment: + kfree(mhi_buf); +error_alloc_mhi_buf: + kfree(img_info); + + return -ENOMEM; +} + int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, struct image_info **image_info, size_t alloc_size) @@ -364,9 +419,9 @@ error_alloc_mhi_buf: return -ENOMEM; } -static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl, - const u8 *buf, size_t remainder, - struct image_info *img_info) +static void mhi_firmware_copy_bhie(struct mhi_controller *mhi_cntrl, + const u8 *buf, size_t remainder, + struct image_info *img_info) { size_t to_cpy; struct mhi_buf *mhi_buf = img_info->mhi_buf; @@ -390,10 +445,9 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) const struct firmware *firmware = NULL; struct device *dev = &mhi_cntrl->mhi_dev->dev; enum mhi_pm_state new_state; + struct image_info *image; const char *fw_name; const u8 *fw_data; - void *buf; - dma_addr_t dma_addr; size_t size, fw_sz; int ret; @@ -452,17 +506,17 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) fw_sz = firmware->size; skip_req_fw: - buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, size, &dma_addr, - GFP_KERNEL); - if (!buf) { + ret = mhi_alloc_bhi_buffer(mhi_cntrl, &image, size); + if (ret) { release_firmware(firmware); goto error_fw_load; } + /* Load the firmware into BHI vec table */ + memcpy(image->mhi_buf->buf, fw_data, size); /* Download image using BHI */ - memcpy(buf, fw_data, size); - ret = mhi_fw_load_bhi(mhi_cntrl, dma_addr, size); - dma_free_coherent(mhi_cntrl->cntrl_dev, size, buf, dma_addr); + ret = mhi_fw_load_bhi(mhi_cntrl, image->mhi_buf); + mhi_free_bhi_buffer(mhi_cntrl, image); /* Error or in EDL mode, we're done */ if (ret) { @@ -493,7 +547,7 @@ skip_req_fw: } /* Load the firmware into BHIE vec table */ - mhi_firmware_copy(mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image); + mhi_firmware_copy_bhie(mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image); } release_firmware(firmware); -- cgit v1.2.3-59-g8ed1b From f88f1d0998ea2e5779a44013dde2a3503322c98e Mon Sep 17 00:00:00 2001 From: Matthew Leung Date: Fri, 17 Jan 2025 10:09:38 -0700 Subject: bus: mhi: host: Add a policy to enable image transfer via BHIe in PBL Currently, MHI host only performs firmware transfer via BHI in PBL and BHIe from SBL. To support BHIe transfer directly from PBL, a policy needs to be added. With this policy, BHIe will be used to transfer firmware in PBL if the MHI controller has BHIe regs, sets seg_len, and does not set fbc_download. The intention is to transfer firmware using BHIe in PBL without further BHIe transfers in SBL. Signed-off-by: Matthew Leung Reviewed-by: Youssef Samir Reviewed-by: Jeffrey Hugo Signed-off-by: Jeffrey Hugo Reviewed-by: Jacek Lawrynowicz Reviewed-by: Manivannan Sadhasivam Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-3-quic_jhugo@quicinc.com --- drivers/bus/mhi/host/boot.c | 73 ++++++++++++++++++++++++++++++++--------- drivers/bus/mhi/host/init.c | 2 +- drivers/bus/mhi/host/internal.h | 7 ++++ 3 files changed, 66 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c index 9fe13d3f09f0..a206c3f0fcfd 100644 --- a/drivers/bus/mhi/host/boot.c +++ b/drivers/bus/mhi/host/boot.c @@ -440,12 +440,59 @@ static void mhi_firmware_copy_bhie(struct mhi_controller *mhi_cntrl, } } +static enum mhi_fw_load_type mhi_fw_load_type_get(const struct mhi_controller *mhi_cntrl) +{ + if (mhi_cntrl->fbc_download) { + return MHI_FW_LOAD_FBC; + } else { + if (mhi_cntrl->seg_len) + return MHI_FW_LOAD_BHIE; + else + return MHI_FW_LOAD_BHI; + } +} + +static int mhi_load_image_bhi(struct mhi_controller *mhi_cntrl, const u8 *fw_data, size_t size) +{ + struct image_info *image; + int ret; + + ret = mhi_alloc_bhi_buffer(mhi_cntrl, &image, size); + if (ret) + return ret; + + /* Load the firmware into BHI vec table */ + memcpy(image->mhi_buf->buf, fw_data, size); + + ret = mhi_fw_load_bhi(mhi_cntrl, &image->mhi_buf[image->entries - 1]); + mhi_free_bhi_buffer(mhi_cntrl, image); + + return ret; +} + +static int mhi_load_image_bhie(struct mhi_controller *mhi_cntrl, const u8 *fw_data, size_t size) +{ + struct image_info *image; + int ret; + + ret = mhi_alloc_bhie_table(mhi_cntrl, &image, size); + if (ret) + return ret; + + mhi_firmware_copy_bhie(mhi_cntrl, fw_data, size, image); + + ret = mhi_fw_load_bhie(mhi_cntrl, &image->mhi_buf[image->entries - 1]); + mhi_free_bhie_table(mhi_cntrl, image); + + return ret; +} + void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) { const struct firmware *firmware = NULL; struct device *dev = &mhi_cntrl->mhi_dev->dev; + enum mhi_fw_load_type fw_load_type; enum mhi_pm_state new_state; - struct image_info *image; const char *fw_name; const u8 *fw_data; size_t size, fw_sz; @@ -506,21 +553,17 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) fw_sz = firmware->size; skip_req_fw: - ret = mhi_alloc_bhi_buffer(mhi_cntrl, &image, size); - if (ret) { - release_firmware(firmware); - goto error_fw_load; - } - /* Load the firmware into BHI vec table */ - memcpy(image->mhi_buf->buf, fw_data, size); - - /* Download image using BHI */ - ret = mhi_fw_load_bhi(mhi_cntrl, image->mhi_buf); - mhi_free_bhi_buffer(mhi_cntrl, image); + fw_load_type = mhi_fw_load_type_get(mhi_cntrl); + if (fw_load_type == MHI_FW_LOAD_BHIE) + ret = mhi_load_image_bhie(mhi_cntrl, fw_data, size); + else + ret = mhi_load_image_bhi(mhi_cntrl, fw_data, size); /* Error or in EDL mode, we're done */ if (ret) { - dev_err(dev, "MHI did not load image over BHI, ret: %d\n", ret); + dev_err(dev, "MHI did not load image over BHI%s, ret: %d\n", + fw_load_type == MHI_FW_LOAD_BHIE ? "e" : "", + ret); release_firmware(firmware); goto error_fw_load; } @@ -539,7 +582,7 @@ skip_req_fw: * If we're doing fbc, populate vector tables while * device transitioning into MHI READY state */ - if (mhi_cntrl->fbc_download) { + if (fw_load_type == MHI_FW_LOAD_FBC) { ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz); if (ret) { release_firmware(firmware); @@ -564,7 +607,7 @@ fw_load_ready_state: return; error_ready_state: - if (mhi_cntrl->fbc_download) { + if (fw_load_type == MHI_FW_LOAD_FBC) { mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); mhi_cntrl->fbc_image = NULL; } diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c index a9b1f8beee7b..13e7a55f54ff 100644 --- a/drivers/bus/mhi/host/init.c +++ b/drivers/bus/mhi/host/init.c @@ -1144,7 +1144,7 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) } mhi_cntrl->bhi = mhi_cntrl->regs + bhi_off; - if (mhi_cntrl->fbc_download || mhi_cntrl->rddm_size) { + if (mhi_cntrl->fbc_download || mhi_cntrl->rddm_size || mhi_cntrl->seg_len) { ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, &bhie_off); if (ret) { diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h index 3134f111be35..ce566f7d2e92 100644 --- a/drivers/bus/mhi/host/internal.h +++ b/drivers/bus/mhi/host/internal.h @@ -29,6 +29,13 @@ struct bhi_vec_entry { u64 size; }; +enum mhi_fw_load_type { + MHI_FW_LOAD_BHI, /* BHI only in PBL */ + MHI_FW_LOAD_BHIE, /* BHIe only in PBL */ + MHI_FW_LOAD_FBC, /* BHI in PBL followed by BHIe in SBL */ + MHI_FW_LOAD_MAX, +}; + enum mhi_ch_state_type { MHI_CH_STATE_TYPE_RESET, MHI_CH_STATE_TYPE_STOP, -- cgit v1.2.3-59-g8ed1b From ab73d80836734bb76088be0da4d2dbf0f7914c2d Mon Sep 17 00:00:00 2001 From: Youssef Samir Date: Fri, 17 Jan 2025 10:09:39 -0700 Subject: accel/qaic: Allocate an exact number of MSIs Devices use 1 MSI vector for the MHI controller and as many vectors as the DMA bridge channels on the device. During the probing of the device, the driver allocates 32 MSI vectors, which is usually more than what is needed for AIC100 devices, which is wasting resources. Allocate only the needed number of MSI vectors per device. Signed-off-by: Youssef Samir Reviewed-by: Troy Hanson Reviewed-by: Jeffrey Hugo Signed-off-by: Jeffrey Hugo Reviewed-by: Lizhi Hou Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-4-quic_jhugo@quicinc.com --- drivers/accel/qaic/qaic_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index 81819b9ef8d4..6e9bed17b3f1 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -465,12 +465,13 @@ static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev) static int init_msi(struct qaic_device *qdev, struct pci_dev *pdev) { + int irq_count = qdev->num_dbc + 1; int mhi_irq; int ret; int i; /* Managed release since we use pcim_enable_device */ - ret = pci_alloc_irq_vectors(pdev, 32, 32, PCI_IRQ_MSI); + ret = pci_alloc_irq_vectors(pdev, irq_count, irq_count, PCI_IRQ_MSI); if (ret == -ENOSPC) { ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); if (ret < 0) @@ -485,7 +486,8 @@ static int init_msi(struct qaic_device *qdev, struct pci_dev *pdev) * interrupted, it shouldn't race with itself. */ qdev->single_msi = true; - pci_info(pdev, "Allocating 32 MSIs failed, operating in 1 MSI mode. Performance may be impacted.\n"); + pci_info(pdev, "Allocating %d MSIs failed, operating in 1 MSI mode. Performance may be impacted.\n", + irq_count); } else if (ret < 0) { return ret; } -- cgit v1.2.3-59-g8ed1b From 0600195ec70a57c3937275e6672927ee6b3c6306 Mon Sep 17 00:00:00 2001 From: Youssef Samir Date: Fri, 17 Jan 2025 10:09:40 -0700 Subject: accel/qaic: Add support for MSI-X AIC200 device will support MSI-X while AIC100 devices will keep using MSI. pci_alloc_irq_vectors() will try to allocate MSI-X vectors if it is supported by the target device, otherwise, it will fallback to MSI. Add support for MSI-X vectors allocation for AIC200 devices. Signed-off-by: Youssef Samir Reviewed-by: Jeffrey Hugo Signed-off-by: Jeffrey Hugo Reviewed-by: Lizhi Hou Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-5-quic_jhugo@quicinc.com --- drivers/accel/qaic/qaic_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index 6e9bed17b3f1..ce0428f6cb82 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -471,9 +471,9 @@ static int init_msi(struct qaic_device *qdev, struct pci_dev *pdev) int i; /* Managed release since we use pcim_enable_device */ - ret = pci_alloc_irq_vectors(pdev, irq_count, irq_count, PCI_IRQ_MSI); + ret = pci_alloc_irq_vectors(pdev, irq_count, irq_count, PCI_IRQ_MSI | PCI_IRQ_MSIX); if (ret == -ENOSPC) { - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI | PCI_IRQ_MSIX); if (ret < 0) return ret; -- cgit v1.2.3-59-g8ed1b From 8685520474bfc0fe4be83c3cbfe3fb3e1ca1514a Mon Sep 17 00:00:00 2001 From: Youssef Samir Date: Fri, 17 Jan 2025 10:09:41 -0700 Subject: accel/qaic: Mask out SR-IOV PCI resources During the initialization of the qaic device, pci_select_bars() is used to fetch a bitmask of the BARs exposed by the device. On devices that have Virtual Functions capabilities, the bitmask includes SR-IOV BARs. Use a mask to filter out SR-IOV BARs if they exist. Signed-off-by: Youssef Samir Reviewed-by: Jeffrey Hugo Signed-off-by: Jeffrey Hugo Reviewed-by: Lizhi Hou Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-6-quic_jhugo@quicinc.com --- drivers/accel/qaic/qaic_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index ce0428f6cb82..00fa07aebacd 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -431,7 +431,7 @@ static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev) int bars; int ret; - bars = pci_select_bars(pdev, IORESOURCE_MEM); + bars = pci_select_bars(pdev, IORESOURCE_MEM) & 0x3f; /* make sure the device has the expected BARs */ if (bars != (BIT(0) | BIT(2) | BIT(4))) { -- cgit v1.2.3-59-g8ed1b From 5bbe412bc7937b5cabfe38aa186a2c6890f70df0 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 17 Jan 2025 10:09:42 -0700 Subject: accel/qaic: Add config structs for supported cards As the number of cards supported by the driver grows, their configurations will differ. The driver needs to become more dynamic to support these configurations. Currently, each card may differ in the exposed BARs, the regions they map to, and the family. Create config structs for each card, and let the driver configure the qaic_device struct based on the configurations passed to the driver. Co-developed-by: Youssef Samir Signed-off-by: Youssef Samir Signed-off-by: Jeffrey Hugo Reviewed-by: Lizhi Hou Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-7-quic_jhugo@quicinc.com --- drivers/accel/qaic/qaic.h | 13 +++++-- drivers/accel/qaic/qaic_drv.c | 76 +++++++++++++++++++++++++------------- drivers/accel/qaic/qaic_timesync.c | 2 +- 3 files changed, 61 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/qaic/qaic.h b/drivers/accel/qaic/qaic.h index 02561b6cecc6..cf97fd9a7e70 100644 --- a/drivers/accel/qaic/qaic.h +++ b/drivers/accel/qaic/qaic.h @@ -32,6 +32,11 @@ #define to_accel_kdev(qddev) (to_drm(qddev)->accel->kdev) /* Return Linux device of accel node */ #define to_qaic_device(dev) (to_qaic_drm_device((dev))->qdev) +enum aic_families { + FAMILY_AIC100, + FAMILY_MAX, +}; + enum __packed dev_states { /* Device is offline or will be very soon */ QAIC_OFFLINE, @@ -113,10 +118,10 @@ struct qaic_device { struct pci_dev *pdev; /* Req. ID of request that will be queued next in MHI control device */ u32 next_seq_num; - /* Base address of bar 0 */ - void __iomem *bar_0; - /* Base address of bar 2 */ - void __iomem *bar_2; + /* Base address of the MHI bar */ + void __iomem *bar_mhi; + /* Base address of the DBCs bar */ + void __iomem *bar_dbc; /* Controller structure for MHI devices */ struct mhi_controller *mhi_cntrl; /* MHI control channel device */ diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index 00fa07aebacd..4e63e475b389 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -34,13 +34,38 @@ MODULE_IMPORT_NS("DMA_BUF"); -#define PCI_DEV_AIC080 0xa080 -#define PCI_DEV_AIC100 0xa100 +#define PCI_DEVICE_ID_QCOM_AIC080 0xa080 +#define PCI_DEVICE_ID_QCOM_AIC100 0xa100 #define QAIC_NAME "qaic" #define QAIC_DESC "Qualcomm Cloud AI Accelerators" #define CNTL_MAJOR 5 #define CNTL_MINOR 0 +struct qaic_device_config { + /* Indicates the AIC family the device belongs to */ + int family; + /* A bitmask representing the available BARs */ + int bar_mask; + /* An index value used to identify the MHI controller BAR */ + unsigned int mhi_bar_idx; + /* An index value used to identify the DBCs BAR */ + unsigned int dbc_bar_idx; +}; + +static const struct qaic_device_config aic080_config = { + .family = FAMILY_AIC100, + .bar_mask = BIT(0) | BIT(2) | BIT(4), + .mhi_bar_idx = 0, + .dbc_bar_idx = 2, +}; + +static const struct qaic_device_config aic100_config = { + .family = FAMILY_AIC100, + .bar_mask = BIT(0) | BIT(2) | BIT(4), + .mhi_bar_idx = 0, + .dbc_bar_idx = 2, +}; + bool datapath_polling; module_param(datapath_polling, bool, 0400); MODULE_PARM_DESC(datapath_polling, "Operate the datapath in polling mode"); @@ -352,7 +377,8 @@ void qaic_dev_reset_clean_local_state(struct qaic_device *qdev) release_dbc(qdev, i); } -static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_device_id *id) +static struct qaic_device *create_qdev(struct pci_dev *pdev, + const struct qaic_device_config *config) { struct device *dev = &pdev->dev; struct qaic_drm_device *qddev; @@ -365,12 +391,10 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_de return NULL; qdev->dev_state = QAIC_OFFLINE; - if (id->device == PCI_DEV_AIC080 || id->device == PCI_DEV_AIC100) { - qdev->num_dbc = 16; - qdev->dbc = devm_kcalloc(dev, qdev->num_dbc, sizeof(*qdev->dbc), GFP_KERNEL); - if (!qdev->dbc) - return NULL; - } + qdev->num_dbc = 16; + qdev->dbc = devm_kcalloc(dev, qdev->num_dbc, sizeof(*qdev->dbc), GFP_KERNEL); + if (!qdev->dbc) + return NULL; qddev = devm_drm_dev_alloc(&pdev->dev, &qaic_accel_driver, struct qaic_drm_device, drm); if (IS_ERR(qddev)) @@ -426,7 +450,8 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_de return qdev; } -static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev) +static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev, + const struct qaic_device_config *config) { int bars; int ret; @@ -434,9 +459,9 @@ static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev) bars = pci_select_bars(pdev, IORESOURCE_MEM) & 0x3f; /* make sure the device has the expected BARs */ - if (bars != (BIT(0) | BIT(2) | BIT(4))) { - pci_dbg(pdev, "%s: expected BARs 0, 2, and 4 not found in device. Found 0x%x\n", - __func__, bars); + if (bars != config->bar_mask) { + pci_dbg(pdev, "%s: expected BARs %#x not found in device. Found %#x\n", + __func__, config->bar_mask, bars); return -EINVAL; } @@ -449,13 +474,13 @@ static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev) return ret; dma_set_max_seg_size(&pdev->dev, UINT_MAX); - qdev->bar_0 = devm_ioremap_resource(&pdev->dev, &pdev->resource[0]); - if (IS_ERR(qdev->bar_0)) - return PTR_ERR(qdev->bar_0); + qdev->bar_mhi = devm_ioremap_resource(&pdev->dev, &pdev->resource[config->mhi_bar_idx]); + if (IS_ERR(qdev->bar_mhi)) + return PTR_ERR(qdev->bar_mhi); - qdev->bar_2 = devm_ioremap_resource(&pdev->dev, &pdev->resource[2]); - if (IS_ERR(qdev->bar_2)) - return PTR_ERR(qdev->bar_2); + qdev->bar_dbc = devm_ioremap_resource(&pdev->dev, &pdev->resource[config->dbc_bar_idx]); + if (IS_ERR(qdev->bar_dbc)) + return PTR_ERR(qdev->bar_dbc); /* Managed release since we use pcim_enable_device above */ pci_set_master(pdev); @@ -517,21 +542,22 @@ static int init_msi(struct qaic_device *qdev, struct pci_dev *pdev) static int qaic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + struct qaic_device_config *config = (struct qaic_device_config *)id->driver_data; struct qaic_device *qdev; int mhi_irq; int ret; int i; - qdev = create_qdev(pdev, id); + qdev = create_qdev(pdev, config); if (!qdev) return -ENOMEM; - ret = init_pci(qdev, pdev); + ret = init_pci(qdev, pdev, config); if (ret) return ret; for (i = 0; i < qdev->num_dbc; ++i) - qdev->dbc[i].dbc_base = qdev->bar_2 + QAIC_DBC_OFF(i); + qdev->dbc[i].dbc_base = qdev->bar_dbc + QAIC_DBC_OFF(i); mhi_irq = init_msi(qdev, pdev); if (mhi_irq < 0) @@ -541,7 +567,7 @@ static int qaic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - qdev->mhi_cntrl = qaic_mhi_register_controller(pdev, qdev->bar_0, mhi_irq, + qdev->mhi_cntrl = qaic_mhi_register_controller(pdev, qdev->bar_mhi, mhi_irq, qdev->single_msi); if (IS_ERR(qdev->mhi_cntrl)) { ret = PTR_ERR(qdev->mhi_cntrl); @@ -609,8 +635,8 @@ static struct mhi_driver qaic_mhi_driver = { }; static const struct pci_device_id qaic_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_QCOM, PCI_DEV_AIC080), }, - { PCI_DEVICE(PCI_VENDOR_ID_QCOM, PCI_DEV_AIC100), }, + { PCI_DEVICE_DATA(QCOM, AIC080, (kernel_ulong_t)&aic080_config), }, + { PCI_DEVICE_DATA(QCOM, AIC100, (kernel_ulong_t)&aic100_config), }, { } }; MODULE_DEVICE_TABLE(pci, qaic_ids); diff --git a/drivers/accel/qaic/qaic_timesync.c b/drivers/accel/qaic/qaic_timesync.c index 301f4462d51b..2473c66309d4 100644 --- a/drivers/accel/qaic/qaic_timesync.c +++ b/drivers/accel/qaic/qaic_timesync.c @@ -201,7 +201,7 @@ static int qaic_timesync_probe(struct mhi_device *mhi_dev, const struct mhi_devi goto free_sync_msg; /* Qtimer register pointer */ - mqtsdev->qtimer_addr = qdev->bar_0 + QTIMER_REG_OFFSET; + mqtsdev->qtimer_addr = qdev->bar_mhi + QTIMER_REG_OFFSET; timer_setup(timer, qaic_timesync_timer, 0); timer->expires = jiffies + msecs_to_jiffies(timesync_delay_ms); add_timer(timer); -- cgit v1.2.3-59-g8ed1b From 7271a88629857dc285d4291055b8e7811f9d3603 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 17 Jan 2025 10:09:43 -0700 Subject: accel/qaic: Add AIC200 support Add basic support for the new AIC200 product. The PCIe Device ID is 0xa110. With this, we can turn on the lights for AIC200 by leveraging much of the existing driver. Co-developed-by: Youssef Samir Signed-off-by: Youssef Samir Signed-off-by: Jeffrey Hugo Reviewed-by: Lizhi Hou Acked-by: Manivannan Sadhasivam Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-8-quic_jhugo@quicinc.com --- drivers/accel/qaic/mhi_controller.c | 360 ++++++++++++++++++++++++++++++++++-- drivers/accel/qaic/mhi_controller.h | 2 +- drivers/accel/qaic/qaic.h | 1 + drivers/accel/qaic/qaic_drv.c | 11 +- drivers/accel/qaic/sahara.c | 39 +++- 5 files changed, 395 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/qaic/mhi_controller.c b/drivers/accel/qaic/mhi_controller.c index 8ab82e78dd94..13a14c6c6168 100644 --- a/drivers/accel/qaic/mhi_controller.c +++ b/drivers/accel/qaic/mhi_controller.c @@ -20,6 +20,11 @@ static unsigned int mhi_timeout_ms = 2000; /* 2 sec default */ module_param(mhi_timeout_ms, uint, 0600); MODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout value"); +static const char *fw_image_paths[FAMILY_MAX] = { + [FAMILY_AIC100] = "qcom/aic100/sbl.bin", + [FAMILY_AIC200] = "qcom/aic200/sbl.bin", +}; + static const struct mhi_channel_config aic100_channels[] = { { .name = "QAIC_LOOPBACK", @@ -439,6 +444,297 @@ static const struct mhi_channel_config aic100_channels[] = { }, }; +static const struct mhi_channel_config aic200_channels[] = { + { + .name = "QAIC_LOOPBACK", + .num = 0, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_LOOPBACK", + .num = 1, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_SAHARA", + .num = 2, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_SBL, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_SAHARA", + .num = 3, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_SBL, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_SSR", + .num = 6, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_SSR", + .num = 7, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_CONTROL", + .num = 10, + .num_elements = 128, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_CONTROL", + .num = 11, + .num_elements = 128, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_LOGGING", + .num = 12, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_SBL, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_LOGGING", + .num = 13, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_SBL, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_STATUS", + .num = 14, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_STATUS", + .num = 15, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_TELEMETRY", + .num = 16, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_TELEMETRY", + .num = 17, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_TIMESYNC_PERIODIC", + .num = 22, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "QAIC_TIMESYNC_PERIODIC", + .num = 23, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "IPCR", + .num = 24, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_TO_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, + .wake_capable = false, + }, + { + .name = "IPCR", + .num = 25, + .num_elements = 32, + .local_elements = 0, + .event_ring = 0, + .dir = DMA_FROM_DEVICE, + .ee_mask = MHI_CH_EE_AMSS, + .pollcfg = 0, + .doorbell = MHI_DB_BRST_DISABLE, + .lpm_notify = false, + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = true, + .wake_capable = false, + }, +}; + static struct mhi_event_config aic100_events[] = { { .num_elements = 32, @@ -454,16 +750,44 @@ static struct mhi_event_config aic100_events[] = { }, }; -static struct mhi_controller_config aic100_config = { - .max_channels = 128, - .timeout_ms = 0, /* controlled by mhi_timeout */ - .buf_len = 0, - .num_channels = ARRAY_SIZE(aic100_channels), - .ch_cfg = aic100_channels, - .num_events = ARRAY_SIZE(aic100_events), - .event_cfg = aic100_events, - .use_bounce_buf = false, - .m2_no_db = false, +static struct mhi_event_config aic200_events[] = { + { + .num_elements = 32, + .irq_moderation_ms = 0, + .irq = 0, + .channel = U32_MAX, + .priority = 1, + .mode = MHI_DB_BRST_DISABLE, + .data_type = MHI_ER_CTRL, + .hardware_event = false, + .client_managed = false, + .offload_channel = false, + }, +}; + +static struct mhi_controller_config mhi_cntrl_configs[] = { + [FAMILY_AIC100] = { + .max_channels = 128, + .timeout_ms = 0, /* controlled by mhi_timeout */ + .buf_len = 0, + .num_channels = ARRAY_SIZE(aic100_channels), + .ch_cfg = aic100_channels, + .num_events = ARRAY_SIZE(aic100_events), + .event_cfg = aic100_events, + .use_bounce_buf = false, + .m2_no_db = false, + }, + [FAMILY_AIC200] = { + .max_channels = 128, + .timeout_ms = 0, /* controlled by mhi_timeout */ + .buf_len = 0, + .num_channels = ARRAY_SIZE(aic200_channels), + .ch_cfg = aic200_channels, + .num_events = ARRAY_SIZE(aic200_events), + .event_cfg = aic200_events, + .use_bounce_buf = false, + .m2_no_db = false, + }, }; static int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 *out) @@ -545,8 +869,9 @@ static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl) } struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar, - int mhi_irq, bool shared_msi) + int mhi_irq, bool shared_msi, int family) { + struct mhi_controller_config mhi_config = mhi_cntrl_configs[family]; struct mhi_controller *mhi_cntrl; int ret; @@ -581,11 +906,18 @@ struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, voi if (shared_msi) /* MSI shared with data path, no IRQF_NO_SUSPEND */ mhi_cntrl->irq_flags = IRQF_SHARED; - mhi_cntrl->fw_image = "qcom/aic100/sbl.bin"; + mhi_cntrl->fw_image = fw_image_paths[family]; + + if (family == FAMILY_AIC200) { + mhi_cntrl->name = "AIC200"; + mhi_cntrl->seg_len = SZ_512K; + } else { + mhi_cntrl->name = "AIC100"; + } /* use latest configured timeout */ - aic100_config.timeout_ms = mhi_timeout_ms; - ret = mhi_register_controller(mhi_cntrl, &aic100_config); + mhi_config.timeout_ms = mhi_timeout_ms; + ret = mhi_register_controller(mhi_cntrl, &mhi_config); if (ret) { pci_err(pci_dev, "mhi_register_controller failed %d\n", ret); return ERR_PTR(ret); diff --git a/drivers/accel/qaic/mhi_controller.h b/drivers/accel/qaic/mhi_controller.h index 500e7f4af2af..8939f6ae185e 100644 --- a/drivers/accel/qaic/mhi_controller.h +++ b/drivers/accel/qaic/mhi_controller.h @@ -8,7 +8,7 @@ #define MHICONTROLLERQAIC_H_ struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar, - int mhi_irq, bool shared_msi); + int mhi_irq, bool shared_msi, int family); void qaic_mhi_free_controller(struct mhi_controller *mhi_cntrl, bool link_up); void qaic_mhi_start_reset(struct mhi_controller *mhi_cntrl); void qaic_mhi_reset_done(struct mhi_controller *mhi_cntrl); diff --git a/drivers/accel/qaic/qaic.h b/drivers/accel/qaic/qaic.h index cf97fd9a7e70..0dbb8e32e4b9 100644 --- a/drivers/accel/qaic/qaic.h +++ b/drivers/accel/qaic/qaic.h @@ -34,6 +34,7 @@ enum aic_families { FAMILY_AIC100, + FAMILY_AIC200, FAMILY_MAX, }; diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index 4e63e475b389..3b415e2c9431 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -36,6 +36,7 @@ MODULE_IMPORT_NS("DMA_BUF"); #define PCI_DEVICE_ID_QCOM_AIC080 0xa080 #define PCI_DEVICE_ID_QCOM_AIC100 0xa100 +#define PCI_DEVICE_ID_QCOM_AIC200 0xa110 #define QAIC_NAME "qaic" #define QAIC_DESC "Qualcomm Cloud AI Accelerators" #define CNTL_MAJOR 5 @@ -66,6 +67,13 @@ static const struct qaic_device_config aic100_config = { .dbc_bar_idx = 2, }; +static const struct qaic_device_config aic200_config = { + .family = FAMILY_AIC200, + .bar_mask = BIT(0) | BIT(1) | BIT(2) | BIT(4), + .mhi_bar_idx = 1, + .dbc_bar_idx = 2, +}; + bool datapath_polling; module_param(datapath_polling, bool, 0400); MODULE_PARM_DESC(datapath_polling, "Operate the datapath in polling mode"); @@ -568,7 +576,7 @@ static int qaic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return ret; qdev->mhi_cntrl = qaic_mhi_register_controller(pdev, qdev->bar_mhi, mhi_irq, - qdev->single_msi); + qdev->single_msi, config->family); if (IS_ERR(qdev->mhi_cntrl)) { ret = PTR_ERR(qdev->mhi_cntrl); qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION); @@ -637,6 +645,7 @@ static struct mhi_driver qaic_mhi_driver = { static const struct pci_device_id qaic_ids[] = { { PCI_DEVICE_DATA(QCOM, AIC080, (kernel_ulong_t)&aic080_config), }, { PCI_DEVICE_DATA(QCOM, AIC100, (kernel_ulong_t)&aic100_config), }, + { PCI_DEVICE_DATA(QCOM, AIC200, (kernel_ulong_t)&aic200_config), }, { } }; MODULE_DEVICE_TABLE(pci, qaic_ids); diff --git a/drivers/accel/qaic/sahara.c b/drivers/accel/qaic/sahara.c index 09c8b055aa81..3ebcc1f7ff58 100644 --- a/drivers/accel/qaic/sahara.c +++ b/drivers/accel/qaic/sahara.c @@ -188,6 +188,34 @@ static const char * const aic100_image_table[] = { [10] = "qcom/aic100/fw10.bin", }; +static const char * const aic200_image_table[] = { + [5] = "qcom/aic200/uefi.elf", + [12] = "qcom/aic200/aic200-nsp.bin", + [23] = "qcom/aic200/aop.mbn", + [32] = "qcom/aic200/tz.mbn", + [33] = "qcom/aic200/hypvm.mbn", + [39] = "qcom/aic200/aic200_abl.elf", + [40] = "qcom/aic200/apdp.mbn", + [41] = "qcom/aic200/devcfg.mbn", + [42] = "qcom/aic200/sec.elf", + [43] = "qcom/aic200/aic200-hlos.elf", + [49] = "qcom/aic200/shrm.elf", + [50] = "qcom/aic200/cpucp.elf", + [51] = "qcom/aic200/aop_devcfg.mbn", + [57] = "qcom/aic200/cpucp_dtbs.elf", + [62] = "qcom/aic200/uefi_dtbs.elf", + [63] = "qcom/aic200/xbl_ac_config.mbn", + [64] = "qcom/aic200/tz_ac_config.mbn", + [65] = "qcom/aic200/hyp_ac_config.mbn", + [66] = "qcom/aic200/pdp.elf", + [67] = "qcom/aic200/pdp_cdb.elf", + [68] = "qcom/aic200/sdi.mbn", + [69] = "qcom/aic200/dcd.mbn", + [73] = "qcom/aic200/gearvm.mbn", + [74] = "qcom/aic200/sti.bin", + [75] = "qcom/aic200/pvs.bin", +}; + static int sahara_find_image(struct sahara_context *context, u32 image_id) { int ret; @@ -748,8 +776,15 @@ static int sahara_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_ context->mhi_dev = mhi_dev; INIT_WORK(&context->fw_work, sahara_processing); INIT_WORK(&context->dump_work, sahara_dump_processing); - context->image_table = aic100_image_table; - context->table_size = ARRAY_SIZE(aic100_image_table); + + if (!strcmp(mhi_dev->mhi_cntrl->name, "AIC200")) { + context->image_table = aic200_image_table; + context->table_size = ARRAY_SIZE(aic200_image_table); + } else { + context->image_table = aic100_image_table; + context->table_size = ARRAY_SIZE(aic100_image_table); + } + context->active_image_id = SAHARA_IMAGE_ID_NONE; dev_set_drvdata(&mhi_dev->dev, context); -- cgit v1.2.3-59-g8ed1b From 34776963452040f199bf9985ad8a2261a82d8b99 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Wed, 29 Jan 2025 13:56:31 +0100 Subject: accel/ivpu: Add support for hardware fault injection Introduces the capability to simulate hardware faults for testing purposes. The new `fail_hw` fault can be injected in `ivpu_hw_reg_poll_fld()`, which is used in various parts of the driver to wait for the hardware to reach a specific state. This allows to test failures during NPU boot and shutdown, IPC message handling and more. Fault injection can be enabled using debugfs or a module parameter. Reviewed-by: Maciej Falkowski Reviewed-by: Jeffrey Hugo Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250129125636.1047413-2-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_debugfs.c | 5 +++ drivers/accel/ivpu/ivpu_hw.c | 14 ++++++++ drivers/accel/ivpu/ivpu_hw_ip.c | 4 +-- drivers/accel/ivpu/ivpu_hw_reg_io.h | 64 +++++++++++++++++++++---------------- 4 files changed, 58 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c index 8180b95ed69d..e79715c53f2a 100644 --- a/drivers/accel/ivpu/ivpu_debugfs.c +++ b/drivers/accel/ivpu/ivpu_debugfs.c @@ -4,6 +4,7 @@ */ #include +#include #include #include @@ -430,4 +431,8 @@ void ivpu_debugfs_init(struct ivpu_device *vdev) debugfs_root, vdev, &fw_profiling_freq_fops); debugfs_create_file("dct", 0644, debugfs_root, vdev, &ivpu_dct_fops); } + +#ifdef CONFIG_FAULT_INJECTION + fault_create_debugfs_attr("fail_hw", debugfs_root, &ivpu_hw_failure); +#endif } diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index e332f19ab51d..8099ab047bfe 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -9,6 +9,15 @@ #include "ivpu_hw_ip.h" #include +#include + +#ifdef CONFIG_FAULT_INJECTION +DECLARE_FAULT_ATTR(ivpu_hw_failure); + +static char *ivpu_fail_hw; +module_param_named_unsafe(fail_hw, ivpu_fail_hw, charp, 0444); +MODULE_PARM_DESC(fail_hw, ",,,"); +#endif static char *platform_to_str(u32 platform) { @@ -247,6 +256,11 @@ int ivpu_hw_init(struct ivpu_device *vdev) timeouts_init(vdev); atomic_set(&vdev->hw->firewall_irq_counter, 0); +#ifdef CONFIG_FAULT_INJECTION + if (ivpu_fail_hw) + setup_fault_attr(&ivpu_hw_failure, ivpu_fail_hw); +#endif + return 0; } diff --git a/drivers/accel/ivpu/ivpu_hw_ip.c b/drivers/accel/ivpu/ivpu_hw_ip.c index 029dd065614b..823f6a57dc54 100644 --- a/drivers/accel/ivpu/ivpu_hw_ip.c +++ b/drivers/accel/ivpu/ivpu_hw_ip.c @@ -968,14 +968,14 @@ void ivpu_hw_ip_wdt_disable(struct ivpu_device *vdev) static u32 ipc_rx_count_get_37xx(struct ivpu_device *vdev) { - u32 count = REGV_RD32_SILENT(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT); + u32 count = readl(vdev->regv + VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT); return REG_GET_FLD(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); } static u32 ipc_rx_count_get_40xx(struct ivpu_device *vdev) { - u32 count = REGV_RD32_SILENT(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT); + u32 count = readl(vdev->regv + VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT); return REG_GET_FLD(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); } diff --git a/drivers/accel/ivpu/ivpu_hw_reg_io.h b/drivers/accel/ivpu/ivpu_hw_reg_io.h index 79b3f441eac4..66259b0ead02 100644 --- a/drivers/accel/ivpu/ivpu_hw_reg_io.h +++ b/drivers/accel/ivpu/ivpu_hw_reg_io.h @@ -7,6 +7,7 @@ #define __IVPU_HW_REG_IO_H__ #include +#include #include #include @@ -16,13 +17,11 @@ #define REG_IO_ERROR 0xffffffff #define REGB_RD32(reg) ivpu_hw_reg_rd32(vdev, vdev->regb, (reg), #reg, __func__) -#define REGB_RD32_SILENT(reg) readl(vdev->regb + (reg)) #define REGB_RD64(reg) ivpu_hw_reg_rd64(vdev, vdev->regb, (reg), #reg, __func__) #define REGB_WR32(reg, val) ivpu_hw_reg_wr32(vdev, vdev->regb, (reg), (val), #reg, __func__) #define REGB_WR64(reg, val) ivpu_hw_reg_wr64(vdev, vdev->regb, (reg), (val), #reg, __func__) #define REGV_RD32(reg) ivpu_hw_reg_rd32(vdev, vdev->regv, (reg), #reg, __func__) -#define REGV_RD32_SILENT(reg) readl(vdev->regv + (reg)) #define REGV_RD64(reg) ivpu_hw_reg_rd64(vdev, vdev->regv, (reg), #reg, __func__) #define REGV_WR32(reg, val) ivpu_hw_reg_wr32(vdev, vdev->regv, (reg), (val), #reg, __func__) #define REGV_WR64(reg, val) ivpu_hw_reg_wr64(vdev, vdev->regv, (reg), (val), #reg, __func__) @@ -47,31 +46,42 @@ #define REG_TEST_FLD_NUM(REG, FLD, num, val) \ ((num) == FIELD_GET(REG##_##FLD##_MASK, val)) -#define REGB_POLL_FLD(reg, fld, val, timeout_us) \ -({ \ - u32 var; \ - int r; \ - ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s started (expected 0x%x)\n", \ - __func__, #reg, reg, #fld, val); \ - r = read_poll_timeout(REGB_RD32_SILENT, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)),\ - REG_POLL_SLEEP_US, timeout_us, false, (reg)); \ - ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s %s (reg val 0x%08x)\n", \ - __func__, #reg, reg, #fld, r ? "ETIMEDOUT" : "OK", var); \ - r; \ -}) - -#define REGV_POLL_FLD(reg, fld, val, timeout_us) \ -({ \ - u32 var; \ - int r; \ - ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s started (expected 0x%x)\n", \ - __func__, #reg, reg, #fld, val); \ - r = read_poll_timeout(REGV_RD32_SILENT, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)),\ - REG_POLL_SLEEP_US, timeout_us, false, (reg)); \ - ivpu_dbg(vdev, REG, "%s : %s (0x%08x) Polling field %s %s (reg val 0x%08x)\n", \ - __func__, #reg, reg, #fld, r ? "ETIMEDOUT" : "OK", var); \ - r; \ -}) +#define REGB_POLL_FLD(reg, fld, exp_fld_val, timeout_us) \ + ivpu_hw_reg_poll_fld(vdev, vdev->regb, reg, reg##_##fld##_MASK, \ + FIELD_PREP(reg##_##fld##_MASK, exp_fld_val), timeout_us, \ + __func__, #reg, #fld) + +#define REGV_POLL_FLD(reg, fld, exp_fld_val, timeout_us) \ + ivpu_hw_reg_poll_fld(vdev, vdev->regv, reg, reg##_##fld##_MASK, \ + FIELD_PREP(reg##_##fld##_MASK, exp_fld_val), timeout_us, \ + __func__, #reg, #fld) + +extern struct fault_attr ivpu_hw_failure; + +static inline int __must_check +ivpu_hw_reg_poll_fld(struct ivpu_device *vdev, void __iomem *base, + u32 reg_offset, u32 reg_mask, u32 exp_masked_val, u32 timeout_us, + const char *func_name, const char *reg_name, const char *fld_name) +{ + u32 reg_val; + int ret; + + ivpu_dbg(vdev, REG, "%s : %s (0x%08x) POLL %s started (exp_val 0x%x)\n", + func_name, reg_name, reg_offset, fld_name, exp_masked_val); + + ret = read_poll_timeout(readl, reg_val, (reg_val & reg_mask) == exp_masked_val, + REG_POLL_SLEEP_US, timeout_us, false, base + reg_offset); + +#ifdef CONFIG_FAULT_INJECTION + if (should_fail(&ivpu_hw_failure, 1)) + ret = -ETIMEDOUT; +#endif + + ivpu_dbg(vdev, REG, "%s : %s (0x%08x) POLL %s %s (reg_val 0x%08x)\n", + func_name, reg_name, reg_offset, fld_name, ret ? "ETIMEDOUT" : "OK", reg_val); + + return ret; +} static inline u32 ivpu_hw_reg_rd32(struct ivpu_device *vdev, void __iomem *base, u32 reg, -- cgit v1.2.3-59-g8ed1b From b8c00323ae65e1bbee9f87a1e66592b589f53b50 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Wed, 29 Jan 2025 13:56:32 +0100 Subject: accel/ivpu: Update last_busy in IRQ handler Call pm_runtime_mark_last_busy() in top half of IRQ handler to prevent device from being runtime suspended before bottom half is executed on a workqueue. Reviewed-by: Karol Wachowski Reviewed-by: Jeffrey Hugo Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250129125636.1047413-3-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_hw.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index 8099ab047bfe..4199f0bbb435 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -10,6 +10,7 @@ #include #include +#include #ifdef CONFIG_FAULT_INJECTION DECLARE_FAULT_ATTR(ivpu_hw_failure); @@ -331,7 +332,9 @@ irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr) /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ ivpu_hw_btrs_global_int_enable(vdev); - if (ip_handled || btrs_handled) - return IRQ_HANDLED; - return IRQ_NONE; + if (!ip_handled && !btrs_handled) + return IRQ_NONE; + + pm_runtime_mark_last_busy(vdev->drm.dev); + return IRQ_HANDLED; } -- cgit v1.2.3-59-g8ed1b From 2f5bbea1807a064a1e4c1b385c8cea4f37bb4b17 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Wed, 29 Jan 2025 13:56:33 +0100 Subject: accel/ivpu: Fix missing MMU events if file_priv is unbound Move the ivpu_mmu_discard_events() function to the common portion of the abort work function. This ensures it is called only once, even if there are no faulty contexts in context_xa, to guarantee that MMU events are discarded and new events are not missed. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Karol Wachowski Reviewed-by: Jeffrey Hugo Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250129125636.1047413-4-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_job.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index 3c162ac41a1d..c1013f511efa 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -375,7 +375,6 @@ void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) ivpu_jsm_context_release(vdev, file_priv->ctx.id); ivpu_mmu_disable_ssid_events(vdev, file_priv->ctx.id); - ivpu_mmu_discard_events(vdev); file_priv->aborted = true; } @@ -980,6 +979,13 @@ void ivpu_context_abort_work_fn(struct work_struct *work) } mutex_unlock(&vdev->context_list_lock); + /* + * We will not receive new MMU event interrupts until existing events are discarded + * however, we want to discard these events only after aborting the faulty context + * to avoid generating new faults from that context + */ + ivpu_mmu_discard_events(vdev); + if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW) return; -- cgit v1.2.3-59-g8ed1b From 3a40d4f4613e437cf78b9b6a28202c6549227459 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Wed, 29 Jan 2025 13:56:34 +0100 Subject: accel/ivpu: Turn on HWS by default on all platforms Hardware scheduling (HWS) is supposed to be supported on all existing platform with recent FW including pre-silicon ones. Turn on HWS by default. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Karol Wachowski Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250129125636.1047413-5-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_fw.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 6cf1fb826d1b..cfe8f79ec5a6 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -148,15 +148,7 @@ ivpu_fw_sched_mode_select(struct ivpu_device *vdev, const struct vpu_firmware_he if (IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, JSM, 3, 24)) return VPU_SCHEDULING_MODE_OS; - switch (ivpu_device_id(vdev)) { - case PCI_DEVICE_ID_MTL: - case PCI_DEVICE_ID_ARL: - case PCI_DEVICE_ID_LNL: - case PCI_DEVICE_ID_PTL_P: - return VPU_SCHEDULING_MODE_HW; - default: - return VPU_SCHEDULING_MODE_OS; - } + return VPU_SCHEDULING_MODE_HW; } static int ivpu_fw_parse(struct ivpu_device *vdev) -- cgit v1.2.3-59-g8ed1b From af80fe138bebea8db089c5062bca9833a2602667 Mon Sep 17 00:00:00 2001 From: Tomasz Rusinowicz Date: Wed, 29 Jan 2025 13:56:35 +0100 Subject: accel/ivpu: Enable recovery and adjust timeouts for fpga Recovery now works on fpga. JSM state dump timeout needs to be really long for the new fpga model releases. Enable punit on fpga. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Tomasz Rusinowicz Reviewed-by: Jeffrey Hugo Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250129125636.1047413-6-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_hw.c | 10 +++++----- drivers/accel/ivpu/ivpu_pm.c | 5 ----- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index 4199f0bbb435..2057907c5aa6 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -58,7 +58,7 @@ static void platform_init(struct ivpu_device *vdev) static void wa_init(struct ivpu_device *vdev) { - vdev->wa.punit_disabled = ivpu_is_fpga(vdev); + vdev->wa.punit_disabled = false; vdev->wa.clear_runtime_mem = false; if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) @@ -87,12 +87,12 @@ static void timeouts_init(struct ivpu_device *vdev) vdev->timeout.autosuspend = -1; vdev->timeout.d0i3_entry_msg = -1; } else if (ivpu_is_fpga(vdev)) { - vdev->timeout.boot = 100000; - vdev->timeout.jsm = 50000; - vdev->timeout.tdr = 2000000; + vdev->timeout.boot = 50; + vdev->timeout.jsm = 15000; + vdev->timeout.tdr = 30000; vdev->timeout.autosuspend = -1; vdev->timeout.d0i3_entry_msg = 500; - vdev->timeout.state_dump_msg = 10; + vdev->timeout.state_dump_msg = 10000; } else if (ivpu_is_simics(vdev)) { vdev->timeout.boot = 50; vdev->timeout.jsm = 500; diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index f41b3bfe40af..8f6222d15720 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -161,11 +161,6 @@ void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason) return; } - if (ivpu_is_fpga(vdev)) { - ivpu_err(vdev, "Recovery not available on FPGA\n"); - return; - } - /* Trigger recovery if it's not in progress */ if (atomic_cmpxchg(&vdev->pm->reset_pending, 0, 1) == 0) { ivpu_hw_diagnose_failure(vdev); -- cgit v1.2.3-59-g8ed1b From d24b85df791840089c2df6a25809aca814b1206d Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Wed, 29 Jan 2025 13:56:36 +0100 Subject: accel/ivpu: Move recovery work to system_unbound_wq Recovery work doesn't need to be bound to any specific CPU, so move it to unbound workqueue to improve execution time and system latency. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Karol Wachowski Reviewed-by: Jeffrey Hugo Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250129125636.1047413-7-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 8f6222d15720..d3db944ad864 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -165,7 +165,7 @@ void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason) if (atomic_cmpxchg(&vdev->pm->reset_pending, 0, 1) == 0) { ivpu_hw_diagnose_failure(vdev); ivpu_hw_irq_disable(vdev); /* Disable IRQ early to protect from IRQ storm */ - queue_work(system_long_wq, &vdev->pm->recovery_work); + queue_work(system_unbound_wq, &vdev->pm->recovery_work); } } -- cgit v1.2.3-59-g8ed1b From 707e860119d5510e897da89492f8a69ae627762c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:01 +0100 Subject: drm/ast: Remove 1152x864 from list of widescreen resolutions The resolution 1152x864 has a ratio of 4:3 and is already handled as such. Remove it from the list of widescreen resolutions. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 9d5321c81e68..b533eb6e233e 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1035,8 +1035,6 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode return MODE_OK; if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) return MODE_OK; - if ((mode->hdisplay == 1152) && (mode->vdisplay == 864)) - return MODE_OK; if ((ast->chip == AST2100) || // GEN2, but not AST1100 (?) (ast->chip == AST2200) || // GEN3, but not AST2150 (?) -- cgit v1.2.3-59-g8ed1b From fdebbb2cec9d53aa6b83847d3762c7783514273a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:02 +0100 Subject: drm/ast: Align naming in widescreen detection code to manual Rename variables and register constants to align with the programming manual. Add new constants where necessary. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.c | 2 +- drivers/gpu/drm/ast/ast_main.c | 8 ++++---- drivers/gpu/drm/ast/ast_post.c | 2 +- drivers/gpu/drm/ast/ast_reg.h | 11 ++++++----- 4 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index cddd69972e89..6fbf62a99c48 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -170,7 +170,7 @@ static int ast_detect_chip(struct pci_dev *pdev, /* Patch AST2500/AST2510 */ if ((pdev->revision & 0xf0) == 0x40) { - if (!(vgacrd0 & AST_VRAM_INIT_STATUS_MASK)) + if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_STATUS_MASK)) ast_patch_ahb_2500(regs); } diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index ba69280b33e7..2a813f0128eb 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -38,7 +38,7 @@ static void ast_detect_widescreen(struct ast_device *ast) { - u8 jreg; + u8 vgacrd0; /* Check if we support wide screen */ switch (AST_GEN(ast)) { @@ -46,10 +46,10 @@ static void ast_detect_widescreen(struct ast_device *ast) ast->support_wide_screen = false; break; default: - jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); - if (!(jreg & 0x80)) + vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0); + if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC)) ast->support_wide_screen = true; - else if (jreg & 0x01) + else if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN) ast->support_wide_screen = true; else { ast->support_wide_screen = false; diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 0daa8e52a092..91e85e457bdf 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -2062,7 +2062,7 @@ void ast_post_chip_2500(struct ast_device *ast) u8 reg; reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); - if ((reg & AST_VRAM_INIT_STATUS_MASK) == 0) {/* vga only */ + if ((reg & AST_IO_VGACRD0_VRAM_INIT_STATUS_MASK) == 0) {/* vga only */ /* Clear bus lock condition */ ast_patch_ahb_2500(ast->regs); diff --git a/drivers/gpu/drm/ast/ast_reg.h b/drivers/gpu/drm/ast/ast_reg.h index 0745d58e5b45..b4ff38949a56 100644 --- a/drivers/gpu/drm/ast/ast_reg.h +++ b/drivers/gpu/drm/ast/ast_reg.h @@ -38,6 +38,12 @@ #define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ #define AST_IO_VGACRCB_HWC_ENABLED BIT(1) +/* mirrors SCU100[7:0] */ +#define AST_IO_VGACRD0_VRAM_INIT_STATUS_MASK GENMASK(7, 6) +#define AST_IO_VGACRD0_VRAM_INIT_BY_BMC BIT(7) +#define AST_IO_VGACRD0_VRAM_INIT_READY BIT(6) +#define AST_IO_VGACRD0_IKVM_WIDESCREEN BIT(0) + #define AST_IO_VGACRD1_MCU_FW_EXECUTING BIT(5) /* Display Transmitter Type */ #define AST_IO_VGACRD1_TX_TYPE_MASK GENMASK(3, 1) @@ -61,11 +67,6 @@ #define AST_IO_VGAIR1_R (0x5A) #define AST_IO_VGAIR1_VREFRESH BIT(3) - -#define AST_VRAM_INIT_STATUS_MASK GENMASK(7, 6) -//#define AST_VRAM_INIT_BY_BMC BIT(7) -//#define AST_VRAM_INIT_READY BIT(6) - /* * AST DisplayPort */ -- cgit v1.2.3-59-g8ed1b From 219c6a4a6f6eada64773bc250cc02c60b5358278 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:03 +0100 Subject: drm/ast: Rename support_wide_screen to support_wsxga_p The flag support_wide_screen in struct ast_device selects devices that support resolutions of at least 1680x1050 (WSXGA+). Name it accordingly. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 2 +- drivers/gpu/drm/ast/ast_main.c | 16 ++++++++-------- drivers/gpu/drm/ast/ast_mode.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index cf9edef8fca6..ec5b204be1da 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -205,7 +205,7 @@ struct ast_device { } astdp; } output; - bool support_wide_screen; + bool support_wsxga_p; /* 1680x1050 */ u8 *dp501_fw_addr; const struct firmware *dp501_fw; /* dp501 fw */ diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 2a813f0128eb..1cfbe404e5a0 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -43,24 +43,24 @@ static void ast_detect_widescreen(struct ast_device *ast) /* Check if we support wide screen */ switch (AST_GEN(ast)) { case 1: - ast->support_wide_screen = false; + ast->support_wsxga_p = false; break; default: vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0); if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC)) - ast->support_wide_screen = true; + ast->support_wsxga_p = true; else if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN) - ast->support_wide_screen = true; + ast->support_wsxga_p = true; else { - ast->support_wide_screen = false; + ast->support_wsxga_p = false; if (ast->chip == AST1300) - ast->support_wide_screen = true; + ast->support_wsxga_p = true; if (ast->chip == AST1400) - ast->support_wide_screen = true; + ast->support_wsxga_p = true; if (ast->chip == AST2510) - ast->support_wide_screen = true; + ast->support_wsxga_p = true; if (IS_AST_GEN7(ast)) - ast->support_wide_screen = true; + ast->support_wsxga_p = true; } break; } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b533eb6e233e..d1b3136b3769 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1024,7 +1024,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode enum drm_mode_status status; uint32_t jtemp; - if (ast->support_wide_screen) { + if (ast->support_wsxga_p) { if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050)) return MODE_OK; if ((mode->hdisplay == 1280) && (mode->vdisplay == 800)) -- cgit v1.2.3-59-g8ed1b From 1bb3f70c418f8ac51a9f19b1f0fe6ddd889794e3 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:04 +0100 Subject: drm/ast: Reorganize widescreen test around hardware Gens Testing for support of widescreen modes mixes up various hardware Gens. First branch by hardware Gen, then do specific tests for each Gen. By default, widesscreen support is disabled. Later patches will add more specific tests for each Gen. v2: - move shared detection code into helper (Jocelyn) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 54 +++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 1cfbe404e5a0..93ae9a275c96 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -36,33 +36,43 @@ #include "ast_drv.h" +/* Try to detect WSXGA+ on Gen2+ */ +static bool __ast_2100_detect_wsxga_p(struct ast_device *ast) +{ + u8 vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0); + + if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC)) + return true; + if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN) + return true; + + return false; +} + static void ast_detect_widescreen(struct ast_device *ast) { - u8 vgacrd0; + ast->support_wsxga_p = false; - /* Check if we support wide screen */ - switch (AST_GEN(ast)) { - case 1: - ast->support_wsxga_p = false; - break; - default: - vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0); - if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC)) + if (AST_GEN(ast) >= 7) { + ast->support_wsxga_p = true; + } else if (AST_GEN(ast) >= 6) { + if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; - else if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN) + else if (ast->chip == AST2510) + ast->support_wsxga_p = true; + } else if (AST_GEN(ast) >= 5) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + else if (ast->chip == AST1400) + ast->support_wsxga_p = true; + } else if (AST_GEN(ast) >= 4) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + else if (ast->chip == AST1300) + ast->support_wsxga_p = true; + } else if (AST_GEN(ast) >= 2) { + if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; - else { - ast->support_wsxga_p = false; - if (ast->chip == AST1300) - ast->support_wsxga_p = true; - if (ast->chip == AST1400) - ast->support_wsxga_p = true; - if (ast->chip == AST2510) - ast->support_wsxga_p = true; - if (IS_AST_GEN7(ast)) - ast->support_wsxga_p = true; - } - break; } } -- cgit v1.2.3-59-g8ed1b From 7a74caabe1013b482b1db10751c79bc75bdaae8c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:05 +0100 Subject: drm/ast: Add support_fullhd flag to struct ast_device Detect support for 1920x1080 (FullHD) in ast_detect_widescreen(). The flag is cleared by default. The test logic has been taken from existing code in ast_crtc_helper_mode_valid(). The code in that function is being replaced by the new flag. For Gen3, a new branch duplicates the Gen2 logic and adds a test for AST2200. Gen2 adds a test for AST2100. v2: - use fullhd flag for setting max width/height Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-6-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_main.c | 19 +++++++++++++++++++ drivers/gpu/drm/ast/ast_mode.c | 12 ++---------- 3 files changed, 22 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index ec5b204be1da..01ef0c0d5db7 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -206,6 +206,7 @@ struct ast_device { } output; bool support_wsxga_p; /* 1680x1050 */ + bool support_fullhd; /* 1920x1080 */ u8 *dp501_fw_addr; const struct firmware *dp501_fw; /* dp501 fw */ diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 93ae9a275c96..6e964a0714b4 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -52,27 +52,46 @@ static bool __ast_2100_detect_wsxga_p(struct ast_device *ast) static void ast_detect_widescreen(struct ast_device *ast) { ast->support_wsxga_p = false; + ast->support_fullhd = false; if (AST_GEN(ast) >= 7) { ast->support_wsxga_p = true; + ast->support_fullhd = true; } else if (AST_GEN(ast) >= 6) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; else if (ast->chip == AST2510) ast->support_wsxga_p = true; + if (ast->support_wsxga_p) + ast->support_fullhd = true; } else if (AST_GEN(ast) >= 5) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; else if (ast->chip == AST1400) ast->support_wsxga_p = true; + if (ast->support_wsxga_p) + ast->support_fullhd = true; } else if (AST_GEN(ast) >= 4) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; else if (ast->chip == AST1300) ast->support_wsxga_p = true; + if (ast->support_wsxga_p) + ast->support_fullhd = true; + } else if (AST_GEN(ast) >= 3) { + if (__ast_2100_detect_wsxga_p(ast)) + ast->support_wsxga_p = true; + if (ast->support_wsxga_p) { + if (ast->chip == AST2200) + ast->support_fullhd = true; + } } else if (AST_GEN(ast) >= 2) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; + if (ast->support_wsxga_p) { + if (ast->chip == AST2100) + ast->support_fullhd = true; + } } } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index d1b3136b3769..dda2c4fb0a48 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1036,10 +1036,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) return MODE_OK; - if ((ast->chip == AST2100) || // GEN2, but not AST1100 (?) - (ast->chip == AST2200) || // GEN3, but not AST2150 (?) - IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || - IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) { + if (ast->support_fullhd) { if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080)) return MODE_OK; @@ -1371,12 +1368,7 @@ int ast_mode_config_init(struct ast_device *ast) dev->mode_config.min_height = 0; dev->mode_config.preferred_depth = 24; - if (ast->chip == AST2100 || // GEN2, but not AST1100 (?) - ast->chip == AST2200 || // GEN3, but not AST2150 (?) - IS_AST_GEN7(ast) || - IS_AST_GEN6(ast) || - IS_AST_GEN5(ast) || - IS_AST_GEN4(ast)) { + if (ast->support_fullhd) { dev->mode_config.max_width = 1920; dev->mode_config.max_height = 2048; } else { -- cgit v1.2.3-59-g8ed1b From 454bdacccac4a020f931bd39a8b8744f765b0ecd Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:06 +0100 Subject: drm/ast: Add support_wuxga flag to struct ast_device Detect support for 1920x1200 (WUXGA) in ast_detect_widescreen(). The flag is cleared by default. The test logic has been taken from existing code in ast_crtc_helper_mode_valid(). The code in that function is being replaced by the new flag. v2: - move shared detection code into helper (Jocelyn) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_main.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/ast/ast_mode.c | 8 +++----- drivers/gpu/drm/ast/ast_reg.h | 1 + 4 files changed, 32 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 01ef0c0d5db7..4e3a88f8a85c 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -207,6 +207,7 @@ struct ast_device { bool support_wsxga_p; /* 1680x1050 */ bool support_fullhd; /* 1920x1080 */ + bool support_wuxga; /* 1920x1200 */ u8 *dp501_fw_addr; const struct firmware *dp501_fw; /* dp501 fw */ diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 6e964a0714b4..44b9b5f659fc 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -49,14 +49,31 @@ static bool __ast_2100_detect_wsxga_p(struct ast_device *ast) return false; } +/* Try to detect WUXGA on Gen2+ */ +static bool __ast_2100_detect_wuxga(struct ast_device *ast) +{ + u8 vgacrd1; + + if (ast->support_fullhd) { + vgacrd1 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd1); + if (!(vgacrd1 & AST_IO_VGACRD1_SUPPORTS_WUXGA)) + return true; + } + + return false; +} + static void ast_detect_widescreen(struct ast_device *ast) { ast->support_wsxga_p = false; ast->support_fullhd = false; + ast->support_wuxga = false; if (AST_GEN(ast) >= 7) { ast->support_wsxga_p = true; ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; } else if (AST_GEN(ast) >= 6) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; @@ -64,6 +81,8 @@ static void ast_detect_widescreen(struct ast_device *ast) ast->support_wsxga_p = true; if (ast->support_wsxga_p) ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; } else if (AST_GEN(ast) >= 5) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; @@ -71,6 +90,8 @@ static void ast_detect_widescreen(struct ast_device *ast) ast->support_wsxga_p = true; if (ast->support_wsxga_p) ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; } else if (AST_GEN(ast) >= 4) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; @@ -78,6 +99,8 @@ static void ast_detect_widescreen(struct ast_device *ast) ast->support_wsxga_p = true; if (ast->support_wsxga_p) ast->support_fullhd = true; + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; } else if (AST_GEN(ast) >= 3) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; @@ -85,6 +108,8 @@ static void ast_detect_widescreen(struct ast_device *ast) if (ast->chip == AST2200) ast->support_fullhd = true; } + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; } else if (AST_GEN(ast) >= 2) { if (__ast_2100_detect_wsxga_p(ast)) ast->support_wsxga_p = true; @@ -92,6 +117,8 @@ static void ast_detect_widescreen(struct ast_device *ast) if (ast->chip == AST2100) ast->support_fullhd = true; } + if (__ast_2100_detect_wuxga(ast)) + ast->support_wuxga = true; } } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index dda2c4fb0a48..bc0c7db5ad46 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1022,7 +1022,6 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode { struct ast_device *ast = to_ast_device(crtc->dev); enum drm_mode_status status; - uint32_t jtemp; if (ast->support_wsxga_p) { if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050)) @@ -1041,11 +1040,10 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode return MODE_OK; if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) { - jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff); - if (jtemp & 0x01) - return MODE_NOMODE; - else + if (ast->support_wuxga) return MODE_OK; + else + return MODE_NOMODE; } } } diff --git a/drivers/gpu/drm/ast/ast_reg.h b/drivers/gpu/drm/ast/ast_reg.h index b4ff38949a56..9db0d584652a 100644 --- a/drivers/gpu/drm/ast/ast_reg.h +++ b/drivers/gpu/drm/ast/ast_reg.h @@ -55,6 +55,7 @@ #define AST_IO_VGACRD1_TX_ANX9807_VBIOS 0x0a #define AST_IO_VGACRD1_TX_FW_EMBEDDED_FW 0x0c /* special case of DP501 */ #define AST_IO_VGACRD1_TX_ASTDP 0x0e +#define AST_IO_VGACRD1_SUPPORTS_WUXGA BIT(0) #define AST_IO_VGACRD7_EDID_VALID_FLAG BIT(0) #define AST_IO_VGACRDC_LINK_SUCCESS BIT(0) -- cgit v1.2.3-59-g8ed1b From 255b3ff65d8ffd70db8c29dda6c8765d58fea2b6 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:07 +0100 Subject: drm/ast: Always validate H/V sync flags The ast driver matches DRM display modes against an internal list of modes supported by the VBIOS. Matching H/V sync flags between modes is preferred, but optional. If sync flags are not matching, the driver would program the VBIOS settings to hardware and let the display handle the difference. DRM modes are generated from attached displays or standard mode lines. Therefore differences to the VBIOS modes are not just cosmetical, but signal possible incompatibility with the display hardware. Hence make matching H/V sync flags mandatory. If the VBIOS does not support a certain mode, we should report it as unsupported. Note that the VBIOS mode tables all appear to refer to standard modes. (If sync flags really make no difference to the VBIOS, the ast driver shouldn't match them in the first place.) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-8-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 45 +++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index bc0c7db5ad46..a484292c9645 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -113,8 +113,8 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, { u32 refresh_rate_index = 0, refresh_rate; const struct ast_vbios_enhtable *best = NULL; + const struct ast_vbios_enhtable *loop; u32 hborder, vborder; - bool check_sync; switch (format->cpp[0] * 8) { case 8: @@ -176,36 +176,27 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, } refresh_rate = drm_mode_vrefresh(mode); - check_sync = vbios_mode->enh_table->flags & WideScreenMode; - - while (1) { - const struct ast_vbios_enhtable *loop = vbios_mode->enh_table; - - while (loop->refresh_rate != 0xff) { - if ((check_sync) && - (((mode->flags & DRM_MODE_FLAG_NVSYNC) && - (loop->flags & PVSync)) || - ((mode->flags & DRM_MODE_FLAG_PVSYNC) && - (loop->flags & NVSync)) || - ((mode->flags & DRM_MODE_FLAG_NHSYNC) && - (loop->flags & PHSync)) || - ((mode->flags & DRM_MODE_FLAG_PHSYNC) && - (loop->flags & NHSync)))) { - loop++; - continue; - } - if (loop->refresh_rate <= refresh_rate - && (!best || loop->refresh_rate > best->refresh_rate)) - best = loop; + + loop = vbios_mode->enh_table; + + while (loop->refresh_rate != 0xff) { + if (((mode->flags & DRM_MODE_FLAG_NVSYNC) && (loop->flags & PVSync)) || + ((mode->flags & DRM_MODE_FLAG_PVSYNC) && (loop->flags & NVSync)) || + ((mode->flags & DRM_MODE_FLAG_NHSYNC) && (loop->flags & PHSync)) || + ((mode->flags & DRM_MODE_FLAG_PHSYNC) && (loop->flags & NHSync))) { loop++; + continue; } - if (best || !check_sync) - break; - check_sync = 0; + if (loop->refresh_rate <= refresh_rate && + (!best || loop->refresh_rate > best->refresh_rate)) + best = loop; + loop++; } - if (best) - vbios_mode->enh_table = best; + if (!best) + return false; + + vbios_mode->enh_table = best; hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; -- cgit v1.2.3-59-g8ed1b From c81202906b5cd56db403e95db3d29c9dfc8c74c1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:08 +0100 Subject: drm/ast: Find VBIOS mode from regular display size The ast driver looks up supplied display modes from an internal list of display modes supported by the VBIOS. Do not use the crtc_-prefixed display values from struct drm_display_mode for looking up the VBIOS mode. The fields contain raw values that the driver programs to hardware. They are affected by display settings like double-scan or interlace. Instead use the regular vdisplay and hdisplay fields for lookup. As the programmed values can now differ from the values used for lookup, set struct drm_display_mode.crtc_vdisplay and .crtc_hdisplay from the VBIOS mode. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-9-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index a484292c9645..961bc2efbc02 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -131,7 +131,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, return false; } - switch (mode->crtc_hdisplay) { + switch (mode->hdisplay) { case 640: vbios_mode->enh_table = &res_640x480[refresh_rate_index]; break; @@ -145,7 +145,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, vbios_mode->enh_table = &res_1152x864[refresh_rate_index]; break; case 1280: - if (mode->crtc_vdisplay == 800) + if (mode->vdisplay == 800) vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; else vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; @@ -157,7 +157,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; break; case 1600: - if (mode->crtc_vdisplay == 900) + if (mode->vdisplay == 900) vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; else vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; @@ -166,7 +166,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; break; case 1920: - if (mode->crtc_vdisplay == 1080) + if (mode->vdisplay == 1080) vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; else vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; @@ -201,6 +201,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; + adjusted_mode->crtc_hdisplay = vbios_mode->enh_table->hde; adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; @@ -210,6 +211,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, vbios_mode->enh_table->hfp + vbios_mode->enh_table->hsync); + adjusted_mode->crtc_vdisplay = vbios_mode->enh_table->vde; adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; -- cgit v1.2.3-59-g8ed1b From 192cc9f2b74a8e3b7d7cc7f4d041698d7ba63efa Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:09 +0100 Subject: drm/ast: Add empty initializer for VBIOS modes VBIOS mode tables are terminated by an entry with a refresh rate of 0xff. The code is hard to read and fragile to use. Therefore create an empty entry with AST_VBIOS_MODE_INVALID to terminate each mode list. Stop at the invalid entry when searching for modes in the tables. Instead of testing for refresh == 0xff, test with a helper function if the mode's size and refresh have meaningful values. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-10-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 2 +- drivers/gpu/drm/ast/ast_tables.h | 52 ++++++++++++++++++---------------------- 2 files changed, 24 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 961bc2efbc02..3f437f871a35 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -179,7 +179,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, loop = vbios_mode->enh_table; - while (loop->refresh_rate != 0xff) { + while (ast_vbios_mode_is_valid(loop)) { if (((mode->flags & DRM_MODE_FLAG_NVSYNC) && (loop->flags & PVSync)) || ((mode->flags & DRM_MODE_FLAG_PVSYNC) && (loop->flags & NVSync)) || ((mode->flags & DRM_MODE_FLAG_NHSYNC) && (loop->flags & PHSync)) || diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h index 0378c9bc079b..4367817b2f80 100644 --- a/drivers/gpu/drm/ast/ast_tables.h +++ b/drivers/gpu/drm/ast/ast_tables.h @@ -24,6 +24,8 @@ #ifndef AST_TABLES_H #define AST_TABLES_H +#include "ast_drv.h" + /* Std. Table Index Definition */ #define TextModeIndex 0 #define EGAModeIndex 1 @@ -212,6 +214,14 @@ static const struct ast_vbios_stdtable vbios_stdtable[] = { }, }; +#define AST_VBIOS_INVALID_MODE \ + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u} + +static inline bool ast_vbios_mode_is_valid(const struct ast_vbios_enhtable *vmode) +{ + return vmode->ht && vmode->vt && vmode->refresh_rate; +} + static const struct ast_vbios_enhtable res_640x480[] = { { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175, /* 60Hz */ (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E }, @@ -221,8 +231,7 @@ static const struct ast_vbios_enhtable res_640x480[] = { (SyncNN | Charx8Dot) , 75, 3, 0x2E }, { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* 85Hz */ (SyncNN | Charx8Dot) , 85, 4, 0x2E }, - { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* end */ - (SyncNN | Charx8Dot) , 0xFF, 4, 0x2E }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_800x600[] = { @@ -236,8 +245,7 @@ static const struct ast_vbios_enhtable res_800x600[] = { (SyncPP | Charx8Dot), 75, 4, 0x30 }, {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25, /* 85Hz */ (SyncPP | Charx8Dot), 84, 5, 0x30 }, - {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25, /* end */ - (SyncPP | Charx8Dot), 0xFF, 5, 0x30 }, + AST_VBIOS_INVALID_MODE, /* end */ }; @@ -250,8 +258,7 @@ static const struct ast_vbios_enhtable res_1024x768[] = { (SyncPP | Charx8Dot), 75, 3, 0x31 }, {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5, /* 85Hz */ (SyncPP | Charx8Dot), 84, 4, 0x31 }, - {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5, /* end */ - (SyncPP | Charx8Dot), 0xFF, 4, 0x31 }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_1280x1024[] = { @@ -261,31 +268,26 @@ static const struct ast_vbios_enhtable res_1280x1024[] = { (SyncPP | Charx8Dot), 75, 2, 0x32 }, {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5, /* 85Hz */ (SyncPP | Charx8Dot), 85, 3, 0x32 }, - {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5, /* end */ - (SyncPP | Charx8Dot), 0xFF, 3, 0x32 }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_1600x1200[] = { {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* 60Hz */ (SyncPP | Charx8Dot), 60, 1, 0x33 }, - {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* end */ - (SyncPP | Charx8Dot), 0xFF, 1, 0x33 }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_1152x864[] = { {1600, 1152, 64, 128, 900, 864, 1, 3, VCLK108, /* 75Hz */ (SyncPP | Charx8Dot | NewModeInfo), 75, 1, 0x3B }, - {1600, 1152, 64, 128, 900, 864, 1, 3, VCLK108, /* end */ - (SyncPP | Charx8Dot | NewModeInfo), 0xFF, 1, 0x3B }, + AST_VBIOS_INVALID_MODE, /* end */ }; /* 16:9 */ static const struct ast_vbios_enhtable res_1360x768[] = { {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 }, - {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* end */ - (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 0xFF, 1, 0x39 }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_1600x900[] = { @@ -294,17 +296,14 @@ static const struct ast_vbios_enhtable res_1600x900[] = { AST2500PreCatchCRT), 60, 1, 0x3A }, {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3A }, - {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x3A }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_1920x1080[] = { {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | AST2500PreCatchCRT), 60, 1, 0x38 }, - {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ - (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 0xFF, 1, 0x38 }, + AST_VBIOS_INVALID_MODE, /* end */ }; @@ -315,8 +314,7 @@ static const struct ast_vbios_enhtable res_1280x800[] = { AST2500PreCatchCRT), 60, 1, 0x35 }, {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 }, - {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x35 }, + AST_VBIOS_INVALID_MODE, /* end */ }; @@ -326,8 +324,7 @@ static const struct ast_vbios_enhtable res_1440x900[] = { AST2500PreCatchCRT), 60, 1, 0x36 }, {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 }, - {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x36 }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_1680x1050[] = { @@ -336,17 +333,14 @@ static const struct ast_vbios_enhtable res_1680x1050[] = { AST2500PreCatchCRT), 60, 1, 0x37 }, {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 }, - {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x37 }, + AST_VBIOS_INVALID_MODE, /* end */ }; static const struct ast_vbios_enhtable res_1920x1200[] = { {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/ (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | AST2500PreCatchCRT), 60, 1, 0x34 }, - {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 0xFF, 1, 0x34 }, + AST_VBIOS_INVALID_MODE, /* end */ }; #endif -- cgit v1.2.3-59-g8ed1b From 517e28d40c9fab2e96b7a88787007954efd6cf50 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:10 +0100 Subject: drm/ast: Add helpers for VBIOS mode lookup Mode lines are independent from hardware Gen or TX chip, so hide all VBIOS mode tables in ast_vbios.c. Move the look-up code for VBIOS modes from ast_vbios_get_mode_info() to ast_vbios_find_mode(). The new look-up function respects the supported-mode flags in struct ast_device. For example, if a device does not have struct ast_device.support_fullhd set, the helper does not return a valid mode for 1920x1080. Taking the supported-mode flags into account allows for making the VBIOS tables the single reference for validating and setting display modes against hardware capabilities. v2: - replace mode switch with look-up table (Jocelyn) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-11-tzimmermann@suse.de --- drivers/gpu/drm/ast/Makefile | 1 + drivers/gpu/drm/ast/ast_dp.c | 1 + drivers/gpu/drm/ast/ast_drv.h | 18 +-- drivers/gpu/drm/ast/ast_mode.c | 77 ++----------- drivers/gpu/drm/ast/ast_tables.h | 177 ---------------------------- drivers/gpu/drm/ast/ast_vbios.c | 241 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/ast/ast_vbios.h | 108 ++++++++++++++++++ 7 files changed, 360 insertions(+), 263 deletions(-) create mode 100644 drivers/gpu/drm/ast/ast_vbios.c create mode 100644 drivers/gpu/drm/ast/ast_vbios.h (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile index 47da848fa3fc..3107ea9c7bf5 100644 --- a/drivers/gpu/drm/ast/Makefile +++ b/drivers/gpu/drm/ast/Makefile @@ -13,6 +13,7 @@ ast-y := \ ast_mode.o \ ast_post.o \ ast_sil164.o \ + ast_vbios.o \ ast_vga.o obj-$(CONFIG_DRM_AST) := ast.o diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 30aad5c0112a..eb65c0881fa7 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -12,6 +12,7 @@ #include #include "ast_drv.h" +#include "ast_vbios.h" static bool ast_astdp_is_connected(struct ast_device *ast) { diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 4e3a88f8a85c..9309cc5e81b0 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -39,6 +39,8 @@ #include "ast_reg.h" +struct ast_vbios_enhtable; + #define DRIVER_AUTHOR "Dave Airlie" #define DRIVER_NAME "ast" @@ -350,22 +352,6 @@ struct ast_vbios_stdtable { u8 gr[9]; }; -struct ast_vbios_enhtable { - u32 ht; - u32 hde; - u32 hfp; - u32 hsync; - u32 vt; - u32 vde; - u32 vfp; - u32 vsync; - u32 dclk_index; - u32 flags; - u32 refresh_rate; - u32 refresh_rate_index; - u32 mode_id; -}; - struct ast_vbios_dclk_info { u8 param1; u8 param2; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 3f437f871a35..14c0c281a683 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -47,6 +47,7 @@ #include "ast_drv.h" #include "ast_tables.h" +#include "ast_vbios.h" #define AST_LUT_SIZE 256 @@ -106,14 +107,12 @@ static void ast_crtc_set_gamma(struct ast_device *ast, } } -static bool ast_get_vbios_mode_info(const struct drm_format_info *format, +static bool ast_get_vbios_mode_info(struct ast_device *ast, + const struct drm_format_info *format, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, struct ast_vbios_mode_info *vbios_mode) { - u32 refresh_rate_index = 0, refresh_rate; - const struct ast_vbios_enhtable *best = NULL; - const struct ast_vbios_enhtable *loop; u32 hborder, vborder; switch (format->cpp[0] * 8) { @@ -131,73 +130,10 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, return false; } - switch (mode->hdisplay) { - case 640: - vbios_mode->enh_table = &res_640x480[refresh_rate_index]; - break; - case 800: - vbios_mode->enh_table = &res_800x600[refresh_rate_index]; - break; - case 1024: - vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; - break; - case 1152: - vbios_mode->enh_table = &res_1152x864[refresh_rate_index]; - break; - case 1280: - if (mode->vdisplay == 800) - vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; - else - vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; - break; - case 1360: - vbios_mode->enh_table = &res_1360x768[refresh_rate_index]; - break; - case 1440: - vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; - break; - case 1600: - if (mode->vdisplay == 900) - vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; - else - vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; - break; - case 1680: - vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; - break; - case 1920: - if (mode->vdisplay == 1080) - vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; - else - vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; - break; - default: - return false; - } - - refresh_rate = drm_mode_vrefresh(mode); - - loop = vbios_mode->enh_table; - - while (ast_vbios_mode_is_valid(loop)) { - if (((mode->flags & DRM_MODE_FLAG_NVSYNC) && (loop->flags & PVSync)) || - ((mode->flags & DRM_MODE_FLAG_PVSYNC) && (loop->flags & NVSync)) || - ((mode->flags & DRM_MODE_FLAG_NHSYNC) && (loop->flags & PHSync)) || - ((mode->flags & DRM_MODE_FLAG_PHSYNC) && (loop->flags & NHSync))) { - loop++; - continue; - } - if (loop->refresh_rate <= refresh_rate && - (!best || loop->refresh_rate > best->refresh_rate)) - best = loop; - loop++; - } - - if (!best) + vbios_mode->enh_table = ast_vbios_find_mode(ast, mode); + if (!vbios_mode->enh_table) return false; - vbios_mode->enh_table = best; - hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; @@ -1109,6 +1045,7 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state); struct drm_device *dev = crtc->dev; + struct ast_device *ast = to_ast_device(dev); struct ast_crtc_state *ast_state; const struct drm_format_info *format; bool succ; @@ -1143,7 +1080,7 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, } } - succ = ast_get_vbios_mode_info(format, &crtc_state->mode, + succ = ast_get_vbios_mode_info(ast, format, &crtc_state->mode, &crtc_state->adjusted_mode, &ast_state->vbios_mode_info); if (!succ) diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h index 4367817b2f80..f1c9f7e1f1fc 100644 --- a/drivers/gpu/drm/ast/ast_tables.h +++ b/drivers/gpu/drm/ast/ast_tables.h @@ -33,54 +33,6 @@ #define HiCModeIndex 3 #define TrueCModeIndex 4 -#define Charx8Dot 0x00000001 -#define HalfDCLK 0x00000002 -#define DoubleScanMode 0x00000004 -#define LineCompareOff 0x00000008 -#define HBorder 0x00000020 -#define VBorder 0x00000010 -#define WideScreenMode 0x00000100 -#define NewModeInfo 0x00000200 -#define NHSync 0x00000400 -#define PHSync 0x00000800 -#define NVSync 0x00001000 -#define PVSync 0x00002000 -#define SyncPP (PVSync | PHSync) -#define SyncPN (PVSync | NHSync) -#define SyncNP (NVSync | PHSync) -#define SyncNN (NVSync | NHSync) -#define AST2500PreCatchCRT 0x00004000 - -/* DCLK Index */ -#define VCLK25_175 0x00 -#define VCLK28_322 0x01 -#define VCLK31_5 0x02 -#define VCLK36 0x03 -#define VCLK40 0x04 -#define VCLK49_5 0x05 -#define VCLK50 0x06 -#define VCLK56_25 0x07 -#define VCLK65 0x08 -#define VCLK75 0x09 -#define VCLK78_75 0x0A -#define VCLK94_5 0x0B -#define VCLK108 0x0C -#define VCLK135 0x0D -#define VCLK157_5 0x0E -#define VCLK162 0x0F -/* #define VCLK193_25 0x10 */ -#define VCLK154 0x10 -#define VCLK83_5 0x11 -#define VCLK106_5 0x12 -#define VCLK146_25 0x13 -#define VCLK148_5 0x14 -#define VCLK71 0x15 -#define VCLK88_75 0x16 -#define VCLK119 0x17 -#define VCLK85_5 0x18 -#define VCLK97_75 0x19 -#define VCLK118_25 0x1A - static const struct ast_vbios_dclk_info dclk_table[] = { {0x2C, 0xE7, 0x03}, /* 00: VCLK25_175 */ {0x95, 0x62, 0x03}, /* 01: VCLK28_322 */ @@ -214,133 +166,4 @@ static const struct ast_vbios_stdtable vbios_stdtable[] = { }, }; -#define AST_VBIOS_INVALID_MODE \ - {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u} - -static inline bool ast_vbios_mode_is_valid(const struct ast_vbios_enhtable *vmode) -{ - return vmode->ht && vmode->vt && vmode->refresh_rate; -} - -static const struct ast_vbios_enhtable res_640x480[] = { - { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175, /* 60Hz */ - (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E }, - { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5, /* 72Hz */ - (SyncNN | HBorder | VBorder | Charx8Dot), 72, 2, 0x2E }, - { 840, 640, 16, 64, 500, 480, 1, 3, VCLK31_5, /* 75Hz */ - (SyncNN | Charx8Dot) , 75, 3, 0x2E }, - { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* 85Hz */ - (SyncNN | Charx8Dot) , 85, 4, 0x2E }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_800x600[] = { - {1024, 800, 24, 72, 625, 600, 1, 2, VCLK36, /* 56Hz */ - (SyncPP | Charx8Dot), 56, 1, 0x30 }, - {1056, 800, 40, 128, 628, 600, 1, 4, VCLK40, /* 60Hz */ - (SyncPP | Charx8Dot), 60, 2, 0x30 }, - {1040, 800, 56, 120, 666, 600, 37, 6, VCLK50, /* 72Hz */ - (SyncPP | Charx8Dot), 72, 3, 0x30 }, - {1056, 800, 16, 80, 625, 600, 1, 3, VCLK49_5, /* 75Hz */ - (SyncPP | Charx8Dot), 75, 4, 0x30 }, - {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25, /* 85Hz */ - (SyncPP | Charx8Dot), 84, 5, 0x30 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - - -static const struct ast_vbios_enhtable res_1024x768[] = { - {1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65, /* 60Hz */ - (SyncNN | Charx8Dot), 60, 1, 0x31 }, - {1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75, /* 70Hz */ - (SyncNN | Charx8Dot), 70, 2, 0x31 }, - {1312, 1024, 16, 96, 800, 768, 1, 3, VCLK78_75, /* 75Hz */ - (SyncPP | Charx8Dot), 75, 3, 0x31 }, - {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5, /* 85Hz */ - (SyncPP | Charx8Dot), 84, 4, 0x31 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_1280x1024[] = { - {1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108, /* 60Hz */ - (SyncPP | Charx8Dot), 60, 1, 0x32 }, - {1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135, /* 75Hz */ - (SyncPP | Charx8Dot), 75, 2, 0x32 }, - {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5, /* 85Hz */ - (SyncPP | Charx8Dot), 85, 3, 0x32 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_1600x1200[] = { - {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* 60Hz */ - (SyncPP | Charx8Dot), 60, 1, 0x33 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_1152x864[] = { - {1600, 1152, 64, 128, 900, 864, 1, 3, VCLK108, /* 75Hz */ - (SyncPP | Charx8Dot | NewModeInfo), 75, 1, 0x3B }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -/* 16:9 */ -static const struct ast_vbios_enhtable res_1360x768[] = { - {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ - (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_1600x900[] = { - {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 60, 1, 0x3A }, - {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60Hz CVT */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3A }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_1920x1080[] = { - {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ - (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 60, 1, 0x38 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - - -/* 16:10 */ -static const struct ast_vbios_enhtable res_1280x800[] = { - {1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 60, 1, 0x35 }, - {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 }, - AST_VBIOS_INVALID_MODE, /* end */ - -}; - -static const struct ast_vbios_enhtable res_1440x900[] = { - {1600, 1440, 48, 32, 926, 900, 3, 6, VCLK88_75, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 60, 1, 0x36 }, - {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_1680x1050[] = { - {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 60, 1, 0x37 }, - {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - -static const struct ast_vbios_enhtable res_1920x1200[] = { - {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz RB*/ - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | - AST2500PreCatchCRT), 60, 1, 0x34 }, - AST_VBIOS_INVALID_MODE, /* end */ -}; - #endif diff --git a/drivers/gpu/drm/ast/ast_vbios.c b/drivers/gpu/drm/ast/ast_vbios.c new file mode 100644 index 000000000000..0953e6dd3976 --- /dev/null +++ b/drivers/gpu/drm/ast/ast_vbios.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2005 ASPEED Technology Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ast_drv.h" +#include "ast_vbios.h" + +/* 4:3 */ + +static const struct ast_vbios_enhtable res_640x480[] = { + { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175, /* 60 Hz */ + (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2e }, + { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5, /* 72 Hz */ + (SyncNN | HBorder | VBorder | Charx8Dot), 72, 2, 0x2e }, + { 840, 640, 16, 64, 500, 480, 1, 3, VCLK31_5, /* 75 Hz */ + (SyncNN | Charx8Dot), 75, 3, 0x2e }, + { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36, /* 85 Hz */ + (SyncNN | Charx8Dot), 85, 4, 0x2e }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_800x600[] = { + { 1024, 800, 24, 72, 625, 600, 1, 2, VCLK36, /* 56 Hz */ + (SyncPP | Charx8Dot), 56, 1, 0x30 }, + { 1056, 800, 40, 128, 628, 600, 1, 4, VCLK40, /* 60 Hz */ + (SyncPP | Charx8Dot), 60, 2, 0x30 }, + { 1040, 800, 56, 120, 666, 600, 37, 6, VCLK50, /* 72 Hz */ + (SyncPP | Charx8Dot), 72, 3, 0x30 }, + { 1056, 800, 16, 80, 625, 600, 1, 3, VCLK49_5, /* 75 Hz */ + (SyncPP | Charx8Dot), 75, 4, 0x30 }, + { 1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25, /* 85 Hz */ + (SyncPP | Charx8Dot), 84, 5, 0x30 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1024x768[] = { + { 1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65, /* 60 Hz */ + (SyncNN | Charx8Dot), 60, 1, 0x31 }, + { 1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75, /* 70 Hz */ + (SyncNN | Charx8Dot), 70, 2, 0x31 }, + { 1312, 1024, 16, 96, 800, 768, 1, 3, VCLK78_75, /* 75 Hz */ + (SyncPP | Charx8Dot), 75, 3, 0x31 }, + { 1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5, /* 85 Hz */ + (SyncPP | Charx8Dot), 84, 4, 0x31 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1152x864[] = { + { 1600, 1152, 64, 128, 900, 864, 1, 3, VCLK108, /* 75 Hz */ + (SyncPP | Charx8Dot | NewModeInfo), 75, 1, 0x3b }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1280x1024[] = { + { 1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108, /* 60 Hz */ + (SyncPP | Charx8Dot), 60, 1, 0x32 }, + { 1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135, /* 75 Hz */ + (SyncPP | Charx8Dot), 75, 2, 0x32 }, + { 1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5, /* 85 Hz */ + (SyncPP | Charx8Dot), 85, 3, 0x32 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1600x1200[] = { + { 2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162, /* 60 Hz */ + (SyncPP | Charx8Dot), 60, 1, 0x33 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +/* 16:9 */ + +static const struct ast_vbios_enhtable res_1360x768[] = { + { 1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5, /* 60 Hz */ + (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1600x900[] = { + { 1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60 Hz CVT RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x3a }, + { 2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25, /* 60 Hz CVT */ + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3a }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1920x1080[] = { + { 2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60 Hz */ + (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x38 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +/* 16:10 */ + +static const struct ast_vbios_enhtable res_1280x800[] = { + { 1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71, /* 60 Hz RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x35 }, + { 1680, 1280, 72, 128, 831, 800, 3, 6, VCLK83_5, /* 60 Hz */ + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1440x900[] = { + { 1600, 1440, 48, 32, 926, 900, 3, 6, VCLK88_75, /* 60 Hz RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x36 }, + { 1904, 1440, 80, 152, 934, 900, 3, 6, VCLK106_5, /* 60 Hz */ + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1680x1050[] = { + { 1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60 Hz RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x37 }, + { 2240, 1680, 104, 176, 1089, 1050, 3, 6, VCLK146_25, /* 60 Hz */ + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +static const struct ast_vbios_enhtable res_1920x1200[] = { + { 2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60 Hz RB*/ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x34 }, + AST_VBIOS_INVALID_MODE, /* end */ +}; + +/* + * VBIOS mode tables + */ + +static const struct ast_vbios_enhtable *res_table_wuxga[] = { + &res_1920x1200[0], + NULL, +}; + +static const struct ast_vbios_enhtable *res_table_fullhd[] = { + &res_1920x1080[0], + NULL, +}; + +static const struct ast_vbios_enhtable *res_table_wsxga_p[] = { + &res_1280x800[0], + &res_1360x768[0], + &res_1440x900[0], + &res_1600x900[0], + &res_1680x1050[0], + NULL, +}; + +static const struct ast_vbios_enhtable *res_table[] = { + &res_640x480[0], + &res_800x600[0], + &res_1024x768[0], + &res_1152x864[0], + &res_1280x1024[0], + &res_1600x1200[0], + NULL, +}; + +static const struct ast_vbios_enhtable * +__ast_vbios_find_mode_table(const struct ast_vbios_enhtable **vmode_tables, + unsigned int hdisplay, + unsigned int vdisplay) +{ + while (*vmode_tables) { + if ((*vmode_tables)->hde == hdisplay && (*vmode_tables)->vde == vdisplay) + return *vmode_tables; + ++vmode_tables; + } + + return NULL; +} + +static const struct ast_vbios_enhtable *ast_vbios_find_mode_table(const struct ast_device *ast, + unsigned int hdisplay, + unsigned int vdisplay) +{ + const struct ast_vbios_enhtable *vmode_table = NULL; + + if (ast->support_wuxga) + vmode_table = __ast_vbios_find_mode_table(res_table_wuxga, hdisplay, vdisplay); + if (!vmode_table && ast->support_fullhd) + vmode_table = __ast_vbios_find_mode_table(res_table_fullhd, hdisplay, vdisplay); + if (!vmode_table && ast->support_wsxga_p) + vmode_table = __ast_vbios_find_mode_table(res_table_wsxga_p, hdisplay, vdisplay); + if (!vmode_table) + vmode_table = __ast_vbios_find_mode_table(res_table, hdisplay, vdisplay); + + return vmode_table; +} + +const struct ast_vbios_enhtable *ast_vbios_find_mode(const struct ast_device *ast, + const struct drm_display_mode *mode) +{ + const struct ast_vbios_enhtable *best_vmode = NULL; + const struct ast_vbios_enhtable *vmode_table; + const struct ast_vbios_enhtable *vmode; + u32 refresh_rate; + + vmode_table = ast_vbios_find_mode_table(ast, mode->hdisplay, mode->vdisplay); + if (!vmode_table) + return NULL; + + refresh_rate = drm_mode_vrefresh(mode); + + for (vmode = vmode_table; ast_vbios_mode_is_valid(vmode); ++vmode) { + if (((mode->flags & DRM_MODE_FLAG_NVSYNC) && (vmode->flags & PVSync)) || + ((mode->flags & DRM_MODE_FLAG_PVSYNC) && (vmode->flags & NVSync)) || + ((mode->flags & DRM_MODE_FLAG_NHSYNC) && (vmode->flags & PHSync)) || + ((mode->flags & DRM_MODE_FLAG_PHSYNC) && (vmode->flags & NHSync))) { + continue; + } + if (vmode->refresh_rate <= refresh_rate && + (!best_vmode || vmode->refresh_rate > best_vmode->refresh_rate)) + best_vmode = vmode; + } + + return best_vmode; +} diff --git a/drivers/gpu/drm/ast/ast_vbios.h b/drivers/gpu/drm/ast/ast_vbios.h new file mode 100644 index 000000000000..8cf025010594 --- /dev/null +++ b/drivers/gpu/drm/ast/ast_vbios.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2005 ASPEED Technology Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* Ported from xf86-video-ast driver */ + +#ifndef AST_VBIOS_H +#define AST_VBIOS_H + +#include + +struct ast_device; +struct drm_display_mode; + +#define Charx8Dot 0x00000001 +#define HalfDCLK 0x00000002 +#define DoubleScanMode 0x00000004 +#define LineCompareOff 0x00000008 +#define HBorder 0x00000020 +#define VBorder 0x00000010 +#define WideScreenMode 0x00000100 +#define NewModeInfo 0x00000200 +#define NHSync 0x00000400 +#define PHSync 0x00000800 +#define NVSync 0x00001000 +#define PVSync 0x00002000 +#define SyncPP (PVSync | PHSync) +#define SyncPN (PVSync | NHSync) +#define SyncNP (NVSync | PHSync) +#define SyncNN (NVSync | NHSync) +#define AST2500PreCatchCRT 0x00004000 + +/* DCLK Index */ +#define VCLK25_175 0x00 +#define VCLK28_322 0x01 +#define VCLK31_5 0x02 +#define VCLK36 0x03 +#define VCLK40 0x04 +#define VCLK49_5 0x05 +#define VCLK50 0x06 +#define VCLK56_25 0x07 +#define VCLK65 0x08 +#define VCLK75 0x09 +#define VCLK78_75 0x0a +#define VCLK94_5 0x0b +#define VCLK108 0x0c +#define VCLK135 0x0d +#define VCLK157_5 0x0e +#define VCLK162 0x0f +/* #define VCLK193_25 0x10 */ +#define VCLK154 0x10 +#define VCLK83_5 0x11 +#define VCLK106_5 0x12 +#define VCLK146_25 0x13 +#define VCLK148_5 0x14 +#define VCLK71 0x15 +#define VCLK88_75 0x16 +#define VCLK119 0x17 +#define VCLK85_5 0x18 +#define VCLK97_75 0x19 +#define VCLK118_25 0x1a + +struct ast_vbios_enhtable { + u32 ht; + u32 hde; + u32 hfp; + u32 hsync; + u32 vt; + u32 vde; + u32 vfp; + u32 vsync; + u32 dclk_index; + u32 flags; + u32 refresh_rate; + u32 refresh_rate_index; + u32 mode_id; +}; + +#define AST_VBIOS_INVALID_MODE \ + {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u} + +static inline bool ast_vbios_mode_is_valid(const struct ast_vbios_enhtable *vmode) +{ + return vmode->ht && vmode->vt && vmode->refresh_rate; +} + +const struct ast_vbios_enhtable *ast_vbios_find_mode(const struct ast_device *ast, + const struct drm_display_mode *mode); + +#endif -- cgit v1.2.3-59-g8ed1b From 2e90349bf44b30478351be4805a640b3bf5accb9 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:11 +0100 Subject: drm/ast: Validate DRM display modes against VBIOS modes Test DRM display modes against the list of modes supported by the VBIOS. The helper will respect the supported-modes flags in struct ast_device. Hence only DRM display modes supported by the VBIOS will be reported; without the current duplication of this information. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-12-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 62 ++++-------------------------------------- 1 file changed, 5 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 14c0c281a683..f58ec35cb3a3 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -950,65 +950,13 @@ static enum drm_mode_status ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) { struct ast_device *ast = to_ast_device(crtc->dev); - enum drm_mode_status status; - - if (ast->support_wsxga_p) { - if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050)) - return MODE_OK; - if ((mode->hdisplay == 1280) && (mode->vdisplay == 800)) - return MODE_OK; - if ((mode->hdisplay == 1440) && (mode->vdisplay == 900)) - return MODE_OK; - if ((mode->hdisplay == 1360) && (mode->vdisplay == 768)) - return MODE_OK; - if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) - return MODE_OK; - - if (ast->support_fullhd) { - if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080)) - return MODE_OK; - - if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) { - if (ast->support_wuxga) - return MODE_OK; - else - return MODE_NOMODE; - } - } - } + const struct ast_vbios_enhtable *vmode; - status = MODE_NOMODE; + vmode = ast_vbios_find_mode(ast, mode); + if (!vmode) + return MODE_NOMODE; - switch (mode->hdisplay) { - case 640: - if (mode->vdisplay == 480) - status = MODE_OK; - break; - case 800: - if (mode->vdisplay == 600) - status = MODE_OK; - break; - case 1024: - if (mode->vdisplay == 768) - status = MODE_OK; - break; - case 1152: - if (mode->vdisplay == 864) - status = MODE_OK; - break; - case 1280: - if (mode->vdisplay == 1024) - status = MODE_OK; - break; - case 1600: - if (mode->vdisplay == 1200) - status = MODE_OK; - break; - default: - break; - } - - return status; + return MODE_OK; } static void ast_crtc_helper_mode_set_nofb(struct drm_crtc *crtc) -- cgit v1.2.3-59-g8ed1b From c337d4c1de88bda6da88477a390c2f7ba87466b6 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:12 +0100 Subject: drm/ast: Inline ast_get_vbios_mode_info() The helper ast_get_vbios_mode_info() retrieves hardware-specific format and display-mode information. Inline the function into its only caller. While at it, also replace a use of struct drm_format_info.cpp with the correct DRM 4CC codes. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-13-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 112 ++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index f58ec35cb3a3..1676958e9768 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -107,59 +107,6 @@ static void ast_crtc_set_gamma(struct ast_device *ast, } } -static bool ast_get_vbios_mode_info(struct ast_device *ast, - const struct drm_format_info *format, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - struct ast_vbios_mode_info *vbios_mode) -{ - u32 hborder, vborder; - - switch (format->cpp[0] * 8) { - case 8: - vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; - break; - case 16: - vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; - break; - case 24: - case 32: - vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; - break; - default: - return false; - } - - vbios_mode->enh_table = ast_vbios_find_mode(ast, mode); - if (!vbios_mode->enh_table) - return false; - - hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; - vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; - - adjusted_mode->crtc_hdisplay = vbios_mode->enh_table->hde; - adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; - adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; - adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; - adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder + - vbios_mode->enh_table->hfp; - adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder + - vbios_mode->enh_table->hfp + - vbios_mode->enh_table->hsync); - - adjusted_mode->crtc_vdisplay = vbios_mode->enh_table->vde; - adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; - adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; - adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; - adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder + - vbios_mode->enh_table->vfp; - adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder + - vbios_mode->enh_table->vfp + - vbios_mode->enh_table->vsync); - - return true; -} - static void ast_set_vbios_color_reg(struct ast_device *ast, const struct drm_format_info *format, const struct ast_vbios_mode_info *vbios_mode) @@ -990,13 +937,17 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state); struct drm_device *dev = crtc->dev; struct ast_device *ast = to_ast_device(dev); struct ast_crtc_state *ast_state; const struct drm_format_info *format; - bool succ; + struct ast_vbios_mode_info *vbios_mode; + const struct ast_vbios_enhtable *vmode; + unsigned int hborder = 0; + unsigned int vborder = 0; int ret; if (!crtc_state->enable) @@ -1028,11 +979,56 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, } } - succ = ast_get_vbios_mode_info(ast, format, &crtc_state->mode, - &crtc_state->adjusted_mode, - &ast_state->vbios_mode_info); - if (!succ) + vbios_mode = &ast_state->vbios_mode_info; + + /* + * Set register tables. + * + * TODO: These tables mix all kinds of fields and should + * probably be resolved into various helper functions. + */ + switch (format->format) { + case DRM_FORMAT_C8: + vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; + break; + case DRM_FORMAT_RGB565: + vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; + break; + case DRM_FORMAT_RGB888: + case DRM_FORMAT_XRGB8888: + vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; + break; + default: + return -EINVAL; + } + + /* + * Find the VBIOS mode and adjust the DRM display mode accordingly. + */ + + vmode = ast_vbios_find_mode(ast, &crtc_state->mode); + if (!vmode) return -EINVAL; + ast_state->vbios_mode_info.enh_table = vmode; + + if (vmode->flags & HBorder) + hborder = 8; + if (vmode->flags & VBorder) + vborder = 8; + + adjusted_mode->crtc_hdisplay = vmode->hde; + adjusted_mode->crtc_hblank_start = vmode->hde + hborder; + adjusted_mode->crtc_hblank_end = vmode->ht - hborder; + adjusted_mode->crtc_hsync_start = vmode->hde + hborder + vmode->hfp; + adjusted_mode->crtc_hsync_end = vmode->hde + hborder + vmode->hfp + vmode->hsync; + adjusted_mode->crtc_htotal = vmode->ht; + + adjusted_mode->crtc_vdisplay = vmode->vde; + adjusted_mode->crtc_vblank_start = vmode->vde + vborder; + adjusted_mode->crtc_vblank_end = vmode->vt - vborder; + adjusted_mode->crtc_vsync_start = vmode->vde + vborder + vmode->vfp; + adjusted_mode->crtc_vsync_end = vmode->vde + vborder + vmode->vfp + vmode->vsync; + adjusted_mode->crtc_vtotal = vmode->vt; return 0; } -- cgit v1.2.3-59-g8ed1b From d86f6beed067309eeea8bf7c91d967f310db98df Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:13 +0100 Subject: drm/ast: astdp: Rework display-mode setting ASTDP requires a mode index, depending on the resolution. Move the look-up code from ast_dp_set_mode() into a separate helper. Inline the rest of the function into its only caller. Rename the variable names and register constants to match the programming manual. As before, the mode-index lookup still happens during the update's atomic commit. Right now, there's no way of doing it during the atomic check. The lookup requires the VBIOS mode, which is not available at the atomic check's invocation. At least warn now if the mode index could not be found. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-14-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_dp.c | 172 +++++++++++++++++++++++------------------- drivers/gpu/drm/ast/ast_reg.h | 18 +---- 2 files changed, 100 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index eb65c0881fa7..3f5e586325a9 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -14,6 +14,82 @@ #include "ast_drv.h" #include "ast_vbios.h" +static int ast_astdp_get_mode_index(const struct ast_vbios_enhtable *vmode) +{ + u8 refresh_rate_index; + + if (vmode->refresh_rate_index < 1 || vmode->refresh_rate_index > 255) + return -EINVAL; + + refresh_rate_index = vmode->refresh_rate_index - 1; + + switch (vmode->hde) { + case 320: + if (vmode->vde == 240) + return ASTDP_320x240_60; + break; + case 400: + if (vmode->vde == 300) + return ASTDP_400x300_60; + break; + case 512: + if (vmode->vde == 384) + return ASTDP_512x384_60; + break; + case 640: + if (vmode->vde == 480) + return (u8)(ASTDP_640x480_60 + (u8)refresh_rate_index); + break; + case 800: + if (vmode->vde == 600) + return (u8)(ASTDP_800x600_56 + (u8)refresh_rate_index); + break; + case 1024: + if (vmode->vde == 768) + return (u8)(ASTDP_1024x768_60 + (u8)refresh_rate_index); + break; + case 1152: + if (vmode->vde == 864) + return ASTDP_1152x864_75; + break; + case 1280: + if (vmode->vde == 800) + return (u8)(ASTDP_1280x800_60_RB - (u8)refresh_rate_index); + if (vmode->vde == 1024) + return (u8)(ASTDP_1280x1024_60 + (u8)refresh_rate_index); + break; + case 1360: + case 1366: + if (vmode->vde == 768) + return ASTDP_1366x768_60; + break; + case 1440: + if (vmode->vde == 900) + return (u8)(ASTDP_1440x900_60_RB - (u8)refresh_rate_index); + break; + case 1600: + if (vmode->vde == 900) + return (u8)(ASTDP_1600x900_60_RB - (u8)refresh_rate_index); + if (vmode->vde == 1200) + return ASTDP_1600x1200_60; + break; + case 1680: + if (vmode->vde == 1050) + return (u8)(ASTDP_1680x1050_60_RB - (u8)refresh_rate_index); + break; + case 1920: + if (vmode->vde == 1080) + return ASTDP_1920x1080_60; + if (vmode->vde == 1200) + return ASTDP_1920x1200_60; + break; + default: + break; + } + + return -EINVAL; +} + static bool ast_astdp_is_connected(struct ast_device *ast) { if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, AST_IO_VGACRDF_HPD)) @@ -228,80 +304,6 @@ static void ast_dp_set_enable(struct ast_device *ast, bool enabled) drm_WARN_ON(dev, !__ast_dp_wait_enable(ast, enabled)); } -static void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode) -{ - struct ast_device *ast = to_ast_device(crtc->dev); - - u32 ulRefreshRateIndex; - u8 ModeIdx; - - ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1; - - switch (crtc->mode.crtc_hdisplay) { - case 320: - ModeIdx = ASTDP_320x240_60; - break; - case 400: - ModeIdx = ASTDP_400x300_60; - break; - case 512: - ModeIdx = ASTDP_512x384_60; - break; - case 640: - ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex); - break; - case 800: - ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex); - break; - case 1024: - ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex); - break; - case 1152: - ModeIdx = ASTDP_1152x864_75; - break; - case 1280: - if (crtc->mode.crtc_vdisplay == 800) - ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex); - else // 1024 - ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex); - break; - case 1360: - case 1366: - ModeIdx = ASTDP_1366x768_60; - break; - case 1440: - ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex); - break; - case 1600: - if (crtc->mode.crtc_vdisplay == 900) - ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex); - else //1200 - ModeIdx = ASTDP_1600x1200_60; - break; - case 1680: - ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex); - break; - case 1920: - if (crtc->mode.crtc_vdisplay == 1080) - ModeIdx = ASTDP_1920x1080_60; - else //1200 - ModeIdx = ASTDP_1920x1200_60; - break; - default: - return; - } - - /* - * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp) - * CRE1[7:0]: MISC1 (default: 0x00) - * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50) - */ - ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE0, ASTDP_AND_CLEAR_MASK, - ASTDP_MISC0_24bpp); - ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1); - ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx); -} - static void ast_wait_for_vretrace(struct ast_device *ast) { unsigned long timeout = jiffies + HZ; @@ -324,11 +326,29 @@ static void ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder *encoder struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { - struct drm_crtc *crtc = crtc_state->crtc; + struct drm_device *dev = encoder->dev; + struct ast_device *ast = to_ast_device(dev); struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; + int mode_index; + u8 vgacre0, vgacre1, vgacre2; + + mode_index = ast_astdp_get_mode_index(vbios_mode_info->enh_table); + if (drm_WARN_ON(dev, mode_index < 0)) + return; + + /* + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp) + * CRE1[7:0]: MISC1 (default: 0x00) + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50) + */ + vgacre0 = AST_IO_VGACRE0_24BPP; + vgacre1 = 0x00; + vgacre2 = mode_index & 0xff; - ast_dp_set_mode(crtc, vbios_mode_info); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xe0, vgacre0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xe1, vgacre1); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xe2, vgacre2); } static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/ast/ast_reg.h b/drivers/gpu/drm/ast/ast_reg.h index 9db0d584652a..bb2cc1d8b84e 100644 --- a/drivers/gpu/drm/ast/ast_reg.h +++ b/drivers/gpu/drm/ast/ast_reg.h @@ -57,10 +57,14 @@ #define AST_IO_VGACRD1_TX_ASTDP 0x0e #define AST_IO_VGACRD1_SUPPORTS_WUXGA BIT(0) +/* + * AST DisplayPort + */ #define AST_IO_VGACRD7_EDID_VALID_FLAG BIT(0) #define AST_IO_VGACRDC_LINK_SUCCESS BIT(0) #define AST_IO_VGACRDF_HPD BIT(0) #define AST_IO_VGACRDF_DP_VIDEO_ENABLE BIT(4) /* mirrors AST_IO_VGACRE3_DP_VIDEO_ENABLE */ +#define AST_IO_VGACRE0_24BPP BIT(5) /* 18 bpp, if unset */ #define AST_IO_VGACRE3_DP_VIDEO_ENABLE BIT(0) #define AST_IO_VGACRE3_DP_PHY_SLEEP BIT(4) #define AST_IO_VGACRE5_EDID_READ_DONE BIT(0) @@ -68,18 +72,4 @@ #define AST_IO_VGAIR1_R (0x5A) #define AST_IO_VGAIR1_VREFRESH BIT(3) -/* - * AST DisplayPort - */ - -/* - * ASTDP setmode registers: - * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp) - * CRE1[7:0]: MISC1 (default: 0x00) - * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50) - */ -#define ASTDP_MISC0_24bpp BIT(5) -#define ASTDP_MISC1 0 -#define ASTDP_AND_CLEAR_MASK 0x00 - #endif -- cgit v1.2.3-59-g8ed1b From 6af7e16c4d818c0d019c0cdb4eb12da6dc720b57 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:14 +0100 Subject: drm/ast: astdp: Look up mode index from table Replace the large switch statement with a look-up table when selecting the mode index. Makes the code easier to read. The table is sorted by resolutions; if run-time overhead from traversal becomes significant, binary search would be a possible optimization. The mode index requires a refresh-rate index to be added or subtracted, which still requires a minimal switch. In the original code, some of the indices did not contain this computation. Those cases would have been equivalent to adding 0, so they are now all subsumed in the switch's default branch. Signed-off-by: Thomas Zimmermann Suggested-by: Jocelyn Falempe Reviewed-by: Jocelyn Falempe v3: - explain the semantics of the new switch statement (Jocelyn) Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-15-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_dp.c | 116 ++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 3f5e586325a9..54b5a350a988 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -14,80 +14,74 @@ #include "ast_drv.h" #include "ast_vbios.h" +struct ast_astdp_mode_index_table_entry { + unsigned int hdisplay; + unsigned int vdisplay; + unsigned int mode_index; +}; + +/* FIXME: Do refresh rate and flags actually matter? */ +static const struct ast_astdp_mode_index_table_entry ast_astdp_mode_index_table[] = { + { 320, 240, ASTDP_320x240_60 }, + { 400, 300, ASTDP_400x300_60 }, + { 512, 384, ASTDP_512x384_60 }, + { 640, 480, ASTDP_640x480_60 }, + { 800, 600, ASTDP_800x600_56 }, + { 1024, 768, ASTDP_1024x768_60 }, + { 1152, 864, ASTDP_1152x864_75 }, + { 1280, 800, ASTDP_1280x800_60_RB }, + { 1280, 1024, ASTDP_1280x1024_60 }, + { 1360, 768, ASTDP_1366x768_60 }, // same as 1366x786 + { 1366, 768, ASTDP_1366x768_60 }, + { 1440, 900, ASTDP_1440x900_60_RB }, + { 1600, 900, ASTDP_1600x900_60_RB }, + { 1600, 1200, ASTDP_1600x1200_60 }, + { 1680, 1050, ASTDP_1680x1050_60_RB }, + { 1920, 1080, ASTDP_1920x1080_60 }, + { 1920, 1200, ASTDP_1920x1200_60 }, + { 0 } +}; + +static int __ast_astdp_get_mode_index(unsigned int hdisplay, unsigned int vdisplay) +{ + const struct ast_astdp_mode_index_table_entry *entry = ast_astdp_mode_index_table; + + while (entry->hdisplay && entry->vdisplay) { + if (entry->hdisplay == hdisplay && entry->vdisplay == vdisplay) + return entry->mode_index; + ++entry; + } + + return -EINVAL; +} + static int ast_astdp_get_mode_index(const struct ast_vbios_enhtable *vmode) { + int mode_index; u8 refresh_rate_index; + mode_index = __ast_astdp_get_mode_index(vmode->hde, vmode->vde); + if (mode_index < 0) + return mode_index; + if (vmode->refresh_rate_index < 1 || vmode->refresh_rate_index > 255) return -EINVAL; - refresh_rate_index = vmode->refresh_rate_index - 1; - switch (vmode->hde) { - case 320: - if (vmode->vde == 240) - return ASTDP_320x240_60; - break; - case 400: - if (vmode->vde == 300) - return ASTDP_400x300_60; - break; - case 512: - if (vmode->vde == 384) - return ASTDP_512x384_60; - break; - case 640: - if (vmode->vde == 480) - return (u8)(ASTDP_640x480_60 + (u8)refresh_rate_index); - break; - case 800: - if (vmode->vde == 600) - return (u8)(ASTDP_800x600_56 + (u8)refresh_rate_index); - break; - case 1024: - if (vmode->vde == 768) - return (u8)(ASTDP_1024x768_60 + (u8)refresh_rate_index); - break; - case 1152: - if (vmode->vde == 864) - return ASTDP_1152x864_75; - break; - case 1280: - if (vmode->vde == 800) - return (u8)(ASTDP_1280x800_60_RB - (u8)refresh_rate_index); - if (vmode->vde == 1024) - return (u8)(ASTDP_1280x1024_60 + (u8)refresh_rate_index); - break; - case 1360: - case 1366: - if (vmode->vde == 768) - return ASTDP_1366x768_60; - break; - case 1440: - if (vmode->vde == 900) - return (u8)(ASTDP_1440x900_60_RB - (u8)refresh_rate_index); - break; - case 1600: - if (vmode->vde == 900) - return (u8)(ASTDP_1600x900_60_RB - (u8)refresh_rate_index); - if (vmode->vde == 1200) - return ASTDP_1600x1200_60; - break; - case 1680: - if (vmode->vde == 1050) - return (u8)(ASTDP_1680x1050_60_RB - (u8)refresh_rate_index); - break; - case 1920: - if (vmode->vde == 1080) - return ASTDP_1920x1080_60; - if (vmode->vde == 1200) - return ASTDP_1920x1200_60; + /* FIXME: Why are we doing this? */ + switch (mode_index) { + case ASTDP_1280x800_60_RB: + case ASTDP_1440x900_60_RB: + case ASTDP_1600x900_60_RB: + case ASTDP_1680x1050_60_RB: + mode_index = (u8)(mode_index - (u8)refresh_rate_index); break; default: + mode_index = (u8)(mode_index + (u8)refresh_rate_index); break; } - return -EINVAL; + return mode_index; } static bool ast_astdp_is_connected(struct ast_device *ast) -- cgit v1.2.3-59-g8ed1b From ec1d13fa90d6b760d01f6054faa9a0884af6c4d3 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:15 +0100 Subject: drm/ast: Remove struct ast_vbios_mode_info The type struct ast_vbios_mode_info used to store information about the color format and display mode. It has outlived its purpose. Inline its fields into struct ast_crtc_state and replace all instances. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-16-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_dp.c | 3 +- drivers/gpu/drm/ast/ast_drv.h | 8 ++---- drivers/gpu/drm/ast/ast_mode.c | 65 +++++++++++++++++++----------------------- 3 files changed, 32 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 54b5a350a988..192e640626c3 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -323,11 +323,10 @@ static void ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder *encoder struct drm_device *dev = encoder->dev; struct ast_device *ast = to_ast_device(dev); struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); - struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; int mode_index; u8 vgacre0, vgacre1, vgacre2; - mode_index = ast_astdp_get_mode_index(vbios_mode_info->enh_table); + mode_index = ast_astdp_get_mode_index(ast_crtc_state->vmode); if (drm_WARN_ON(dev, mode_index < 0)) return; diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 9309cc5e81b0..022a8c070c1b 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -358,18 +358,14 @@ struct ast_vbios_dclk_info { u8 param3; }; -struct ast_vbios_mode_info { - const struct ast_vbios_stdtable *std_table; - const struct ast_vbios_enhtable *enh_table; -}; - struct ast_crtc_state { struct drm_crtc_state base; /* Last known format of primary plane */ const struct drm_format_info *format; - struct ast_vbios_mode_info vbios_mode_info; + const struct ast_vbios_stdtable *std_table; + const struct ast_vbios_enhtable *vmode; }; #define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 1676958e9768..a93994b00f40 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -109,7 +109,7 @@ static void ast_crtc_set_gamma(struct ast_device *ast, static void ast_set_vbios_color_reg(struct ast_device *ast, const struct drm_format_info *format, - const struct ast_vbios_mode_info *vbios_mode) + const struct ast_vbios_enhtable *vmode) { u32 color_index; @@ -132,7 +132,7 @@ static void ast_set_vbios_color_reg(struct ast_device *ast, ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0x00); - if (vbios_mode->enh_table->flags & NewModeInfo) { + if (vmode->flags & NewModeInfo) { ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0xa8); ast_set_index_reg(ast, AST_IO_VGACRI, 0x92, format->cpp[0] * 8); } @@ -140,19 +140,19 @@ static void ast_set_vbios_color_reg(struct ast_device *ast, static void ast_set_vbios_mode_reg(struct ast_device *ast, const struct drm_display_mode *adjusted_mode, - const struct ast_vbios_mode_info *vbios_mode) + const struct ast_vbios_enhtable *vmode) { u32 refresh_rate_index, mode_id; - refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; - mode_id = vbios_mode->enh_table->mode_id; + refresh_rate_index = vmode->refresh_rate_index; + mode_id = vmode->mode_id; ast_set_index_reg(ast, AST_IO_VGACRI, 0x8d, refresh_rate_index & 0xff); ast_set_index_reg(ast, AST_IO_VGACRI, 0x8e, mode_id & 0xff); ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0x00); - if (vbios_mode->enh_table->flags & NewModeInfo) { + if (vmode->flags & NewModeInfo) { ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0xa8); ast_set_index_reg(ast, AST_IO_VGACRI, 0x93, adjusted_mode->clock / 1000); ast_set_index_reg(ast, AST_IO_VGACRI, 0x94, adjusted_mode->crtc_hdisplay); @@ -164,14 +164,11 @@ static void ast_set_vbios_mode_reg(struct ast_device *ast, static void ast_set_std_reg(struct ast_device *ast, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) + const struct ast_vbios_stdtable *stdtable) { - const struct ast_vbios_stdtable *stdtable; u32 i; u8 jreg; - stdtable = vbios_mode->std_table; - jreg = stdtable->misc; ast_io_write8(ast, AST_IO_VGAMR_W, jreg); @@ -212,13 +209,13 @@ static void ast_set_std_reg(struct ast_device *ast, static void ast_set_crtc_reg(struct ast_device *ast, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) + const struct ast_vbios_enhtable *vmode) { u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0; u16 temp, precache = 0; if ((IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) && - (vbios_mode->enh_table->flags & AST2500PreCatchCRT)) + (vmode->flags & AST2500PreCatchCRT)) precache = 40; ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x7f, 0x00); @@ -337,14 +334,14 @@ static void ast_set_offset_reg(struct ast_device *ast, static void ast_set_dclk_reg(struct ast_device *ast, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) + const struct ast_vbios_enhtable *vmode) { const struct ast_vbios_dclk_info *clk_info; if (IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) - clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index]; + clk_info = &dclk_table_ast2500[vmode->dclk_index]; else - clk_info = &dclk_table[vbios_mode->enh_table->dclk_index]; + clk_info = &dclk_table[vmode->dclk_index]; ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xc0, 0x00, clk_info->param1); ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xc1, 0x00, clk_info->param2); @@ -402,15 +399,15 @@ static void ast_set_crtthd_reg(struct ast_device *ast) static void ast_set_sync_reg(struct ast_device *ast, struct drm_display_mode *mode, - struct ast_vbios_mode_info *vbios_mode) + const struct ast_vbios_enhtable *vmode) { u8 jreg; jreg = ast_io_read8(ast, AST_IO_VGAMR_R); jreg &= ~0xC0; - if (vbios_mode->enh_table->flags & NVSync) + if (vmode->flags & NVSync) jreg |= 0x80; - if (vbios_mode->enh_table->flags & NHSync) + if (vmode->flags & NHSync) jreg |= 0x40; ast_io_write8(ast, AST_IO_VGAMR_W, jreg); } @@ -530,10 +527,9 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane, if (!old_fb || (fb->format != old_fb->format) || crtc_state->mode_changed) { struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); - struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; ast_set_color_reg(ast, fb->format); - ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info); + ast_set_vbios_color_reg(ast, fb->format, ast_crtc_state->vmode); } drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); @@ -912,8 +908,8 @@ static void ast_crtc_helper_mode_set_nofb(struct drm_crtc *crtc) struct ast_device *ast = to_ast_device(dev); struct drm_crtc_state *crtc_state = crtc->state; struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); - struct ast_vbios_mode_info *vbios_mode_info = - &ast_crtc_state->vbios_mode_info; + const struct ast_vbios_stdtable *std_table = ast_crtc_state->std_table; + const struct ast_vbios_enhtable *vmode = ast_crtc_state->vmode; struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; /* @@ -924,13 +920,13 @@ static void ast_crtc_helper_mode_set_nofb(struct drm_crtc *crtc) */ ast_wait_for_vretrace(ast); - ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info); + ast_set_vbios_mode_reg(ast, adjusted_mode, vmode); ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06); - ast_set_std_reg(ast, adjusted_mode, vbios_mode_info); - ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info); - ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info); + ast_set_std_reg(ast, adjusted_mode, std_table); + ast_set_crtc_reg(ast, adjusted_mode, vmode); + ast_set_dclk_reg(ast, adjusted_mode, vmode); ast_set_crtthd_reg(ast); - ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info); + ast_set_sync_reg(ast, adjusted_mode, vmode); } static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, @@ -944,7 +940,6 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, struct ast_device *ast = to_ast_device(dev); struct ast_crtc_state *ast_state; const struct drm_format_info *format; - struct ast_vbios_mode_info *vbios_mode; const struct ast_vbios_enhtable *vmode; unsigned int hborder = 0; unsigned int vborder = 0; @@ -979,8 +974,6 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, } } - vbios_mode = &ast_state->vbios_mode_info; - /* * Set register tables. * @@ -989,14 +982,14 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, */ switch (format->format) { case DRM_FORMAT_C8: - vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; + ast_state->std_table = &vbios_stdtable[VGAModeIndex]; break; case DRM_FORMAT_RGB565: - vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; + ast_state->std_table = &vbios_stdtable[HiCModeIndex]; break; case DRM_FORMAT_RGB888: case DRM_FORMAT_XRGB8888: - vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; + ast_state->std_table = &vbios_stdtable[TrueCModeIndex]; break; default: return -EINVAL; @@ -1009,7 +1002,7 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, vmode = ast_vbios_find_mode(ast, &crtc_state->mode); if (!vmode) return -EINVAL; - ast_state->vbios_mode_info.enh_table = vmode; + ast_state->vmode = vmode; if (vmode->flags & HBorder) hborder = 8; @@ -1130,8 +1123,8 @@ ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) ast_state = to_ast_crtc_state(crtc->state); new_ast_state->format = ast_state->format; - memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info, - sizeof(new_ast_state->vbios_mode_info)); + new_ast_state->std_table = ast_state->std_table; + new_ast_state->vmode = ast_state->vmode; return &new_ast_state->base; } -- cgit v1.2.3-59-g8ed1b From 0c5f9cb67897fc48aef8883d21a8d74d11a2f8e3 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 31 Jan 2025 10:21:16 +0100 Subject: drm/ast: Only look up VBIOS mode on full modesets Only look up the VBIOS mode during atomic_check if the display mode changes. For page flips, the previous settings still apply. Avoids the runtime overhead of looking up the VBIOS mode on each page flip. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-17-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 52 ++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index a93994b00f40..bd781293b6d9 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -996,32 +996,34 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, } /* - * Find the VBIOS mode and adjust the DRM display mode accordingly. + * Find the VBIOS mode and adjust the DRM display mode accordingly + * if a full modeset is required. Otherwise keep the existing values. */ - - vmode = ast_vbios_find_mode(ast, &crtc_state->mode); - if (!vmode) - return -EINVAL; - ast_state->vmode = vmode; - - if (vmode->flags & HBorder) - hborder = 8; - if (vmode->flags & VBorder) - vborder = 8; - - adjusted_mode->crtc_hdisplay = vmode->hde; - adjusted_mode->crtc_hblank_start = vmode->hde + hborder; - adjusted_mode->crtc_hblank_end = vmode->ht - hborder; - adjusted_mode->crtc_hsync_start = vmode->hde + hborder + vmode->hfp; - adjusted_mode->crtc_hsync_end = vmode->hde + hborder + vmode->hfp + vmode->hsync; - adjusted_mode->crtc_htotal = vmode->ht; - - adjusted_mode->crtc_vdisplay = vmode->vde; - adjusted_mode->crtc_vblank_start = vmode->vde + vborder; - adjusted_mode->crtc_vblank_end = vmode->vt - vborder; - adjusted_mode->crtc_vsync_start = vmode->vde + vborder + vmode->vfp; - adjusted_mode->crtc_vsync_end = vmode->vde + vborder + vmode->vfp + vmode->vsync; - adjusted_mode->crtc_vtotal = vmode->vt; + if (drm_atomic_crtc_needs_modeset(crtc_state)) { + vmode = ast_vbios_find_mode(ast, &crtc_state->mode); + if (!vmode) + return -EINVAL; + ast_state->vmode = vmode; + + if (vmode->flags & HBorder) + hborder = 8; + if (vmode->flags & VBorder) + vborder = 8; + + adjusted_mode->crtc_hdisplay = vmode->hde; + adjusted_mode->crtc_hblank_start = vmode->hde + hborder; + adjusted_mode->crtc_hblank_end = vmode->ht - hborder; + adjusted_mode->crtc_hsync_start = vmode->hde + hborder + vmode->hfp; + adjusted_mode->crtc_hsync_end = vmode->hde + hborder + vmode->hfp + vmode->hsync; + adjusted_mode->crtc_htotal = vmode->ht; + + adjusted_mode->crtc_vdisplay = vmode->vde; + adjusted_mode->crtc_vblank_start = vmode->vde + vborder; + adjusted_mode->crtc_vblank_end = vmode->vt - vborder; + adjusted_mode->crtc_vsync_start = vmode->vde + vborder + vmode->vfp; + adjusted_mode->crtc_vsync_end = vmode->vde + vborder + vmode->vfp + vmode->vsync; + adjusted_mode->crtc_vtotal = vmode->vt; + } return 0; } -- cgit v1.2.3-59-g8ed1b From 56b0337d429356c3b9ecc36a03023c8cc856b196 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:49:54 +0200 Subject: drm/i915/dp: Iterate DSC BPP from high to low on all platforms Commit 1c56e9a39833 ("drm/i915/dp: Get optimal link config to have best compressed bpp") tries to find the best compressed bpp for the link. However, it iterates from max to min bpp on display 13+, and from min to max on other platforms. This presumably leads to minimum compressed bpp always being chosen on display 11-12. Iterate from high to low on all platforms to actually use the best possible compressed bpp. Fixes: 1c56e9a39833 ("drm/i915/dp: Get optimal link config to have best compressed bpp") Cc: Ankit Nautiyal Cc: Imre Deak Cc: # v6.7+ Reviewed-by: Imre Deak Reviewed-by: Ankit Nautiyal Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/3bba67923cbcd13a59d26ef5fa4bb042b13c8a9b.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 00aba97631a9..f2c4afc5997c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2073,11 +2073,10 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, /* Compressed BPP should be less than the Input DSC bpp */ dsc_max_bpp = min(dsc_max_bpp, output_bpp - 1); - for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) { - if (valid_dsc_bpp[i] < dsc_min_bpp) + for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) { + if (valid_dsc_bpp[i] < dsc_min_bpp || + valid_dsc_bpp[i] > dsc_max_bpp) continue; - if (valid_dsc_bpp[i] > dsc_max_bpp) - break; ret = dsc_compute_link_config(intel_dp, pipe_config, -- cgit v1.2.3-59-g8ed1b From dc9ea8777c8b999f6a7e9eb974b2f7ae5e643d9b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Sat, 1 Feb 2025 01:28:15 +0200 Subject: drm/i915/dp: Add intel_dp_dsc_bpp_step_x16() helper to get DSC BPP precision Add a platform independent helper for getting the supported DSC BPP step for the link. v2: Use fxp_q4_from_int(1) (Imre) Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20250131232815.2046237-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f2c4afc5997c..43c6f0ad0c01 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2054,6 +2054,21 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp) return 27; } +/* + * Note: for pre-13 display you still need to check the validity of each step. + */ +static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) +{ + struct intel_display *display = to_intel_display(connector); + u8 incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd); + + if (DISPLAY_VER(display) < 14 || !incr) + return fxp_q4_from_int(1); + + /* fxp q4 */ + return fxp_q4_from_int(1) / incr; +} + /* * From a list of valid compressed bpps try different compressed bpp and find a * suitable link configuration that can support it. @@ -2110,16 +2125,12 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, int timeslots) { struct intel_display *display = to_intel_display(intel_dp); - u8 bppx16_incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd); int output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); u16 compressed_bppx16; u8 bppx16_step; int ret; - if (DISPLAY_VER(display) < 14 || bppx16_incr <= 1) - bppx16_step = 16; - else - bppx16_step = 16 / bppx16_incr; + bppx16_step = intel_dp_dsc_bpp_step_x16(connector); /* Compressed BPP should be less than the Input DSC bpp */ dsc_max_bpp = min(dsc_max_bpp << 4, (output_bpp << 4) - bppx16_step); -- cgit v1.2.3-59-g8ed1b From 2e74748c4c0249930c8edcf5ae7b6e5c8c391f7a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:49:56 +0200 Subject: drm/i915/dp: Rename some variables in xelpd_dsc_compute_link_config() Use the _x16 suffix for all .4 fixed point variables. Drop compressed_ prefix, as it's implied from the precision suffix. As dsc_min_bpp and dsc_max_bpp change domain from int to .4 in the middle of the function, they remain the same for now. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/91dd6ef53683b624a978101cca7322ea3e5e2f7b.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 43c6f0ad0c01..e2d252e15ce9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2126,31 +2126,28 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, { struct intel_display *display = to_intel_display(intel_dp); int output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); - u16 compressed_bppx16; - u8 bppx16_step; + int bpp_x16, bpp_step_x16; int ret; - bppx16_step = intel_dp_dsc_bpp_step_x16(connector); + bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); /* Compressed BPP should be less than the Input DSC bpp */ - dsc_max_bpp = min(dsc_max_bpp << 4, (output_bpp << 4) - bppx16_step); + dsc_max_bpp = min(dsc_max_bpp << 4, (output_bpp << 4) - bpp_step_x16); dsc_min_bpp = dsc_min_bpp << 4; - for (compressed_bppx16 = dsc_max_bpp; - compressed_bppx16 >= dsc_min_bpp; - compressed_bppx16 -= bppx16_step) { + for (bpp_x16 = dsc_max_bpp; bpp_x16 >= dsc_min_bpp; bpp_x16 -= bpp_step_x16) { if (intel_dp->force_dsc_fractional_bpp_en && - !fxp_q4_to_frac(compressed_bppx16)) + !fxp_q4_to_frac(bpp_x16)) continue; ret = dsc_compute_link_config(intel_dp, pipe_config, limits, - compressed_bppx16, + bpp_x16, timeslots); if (ret == 0) { - pipe_config->dsc.compressed_bpp_x16 = compressed_bppx16; + pipe_config->dsc.compressed_bpp_x16 = bpp_x16; if (intel_dp->force_dsc_fractional_bpp_en && - fxp_q4_to_frac(compressed_bppx16)) + fxp_q4_to_frac(bpp_x16)) drm_dbg_kms(display->drm, "Forcing DSC fractional bpp\n"); -- cgit v1.2.3-59-g8ed1b From 99f4cb4fb222b42703b43551d55c9ec2520d9d5b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:49:57 +0200 Subject: drm/i915/dp: Pass .4 BPP values to {icl,xelpd}_dsc_compute_link_config() Try to keep the variables in the same domain a bit longer to reduce juggling between integers and .4 fixed point. Change parameter order to min, max while at it. For now, keep the juggling in dsc_compute_compressed_bpp() ensure min/max will always have 0 fractional part. To be fixed later. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/e72f153fd28755e41ee8c5a7b9e6de257c3b27ac.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e2d252e15ce9..0e941307f399 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2077,8 +2077,8 @@ static int icl_dsc_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, const struct link_config_limits *limits, - int dsc_max_bpp, - int dsc_min_bpp, + int min_bpp_x16, + int max_bpp_x16, int pipe_bpp, int timeslots) { @@ -2086,11 +2086,11 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, int output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); /* Compressed BPP should be less than the Input DSC bpp */ - dsc_max_bpp = min(dsc_max_bpp, output_bpp - 1); + max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp - 1)); for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) { - if (valid_dsc_bpp[i] < dsc_min_bpp || - valid_dsc_bpp[i] > dsc_max_bpp) + if (valid_dsc_bpp[i] < fxp_q4_to_int(min_bpp_x16) || + valid_dsc_bpp[i] > fxp_q4_to_int(max_bpp_x16)) continue; ret = dsc_compute_link_config(intel_dp, @@ -2119,8 +2119,8 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, const struct intel_connector *connector, struct intel_crtc_state *pipe_config, const struct link_config_limits *limits, - int dsc_max_bpp, - int dsc_min_bpp, + int min_bpp_x16, + int max_bpp_x16, int pipe_bpp, int timeslots) { @@ -2132,10 +2132,9 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); /* Compressed BPP should be less than the Input DSC bpp */ - dsc_max_bpp = min(dsc_max_bpp << 4, (output_bpp << 4) - bpp_step_x16); - dsc_min_bpp = dsc_min_bpp << 4; + max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); - for (bpp_x16 = dsc_max_bpp; bpp_x16 >= dsc_min_bpp; bpp_x16 -= bpp_step_x16) { + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { if (intel_dp->force_dsc_fractional_bpp_en && !fxp_q4_to_frac(bpp_x16)) continue; @@ -2168,6 +2167,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int dsc_min_bpp; int dsc_max_bpp; + int min_bpp_x16, max_bpp_x16; int dsc_joiner_max_bpp; int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config); @@ -2178,11 +2178,15 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, num_joined_pipes); dsc_max_bpp = min(dsc_joiner_max_bpp, fxp_q4_to_int(limits->link.max_bpp_x16)); + /* FIXME: remove the round trip via integers */ + min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp); + max_bpp_x16 = fxp_q4_from_int(dsc_max_bpp); + if (DISPLAY_VER(display) >= 13) return xelpd_dsc_compute_link_config(intel_dp, connector, pipe_config, limits, - dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots); + min_bpp_x16, max_bpp_x16, pipe_bpp, timeslots); return icl_dsc_compute_link_config(intel_dp, pipe_config, limits, - dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots); + min_bpp_x16, max_bpp_x16, pipe_bpp, timeslots); } int intel_dp_dsc_min_src_input_bpc(void) -- cgit v1.2.3-59-g8ed1b From a38619fc93ade0d5531f88b990825fbf50a79071 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:49:58 +0200 Subject: drm/i915/dp: Move max DSC BPP reduction one level higher Now that {icl,xelpd}_dsc_compute_link_config() take .4 fixed point as parameter, move the common max DSC BPP reduction one level higher. Use intel_dp_dsc_bpp_step() to compute the step, and pass on to both platform specific functions. (Though it's unused for now in icl_dsc_compute_link_config()). We can drop the pipe_bpp and connector parameters. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/62fa7f18ea49dce24c5d0ee7b2f0cbde9e2b609c.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0e941307f399..898846d61c63 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2079,14 +2079,10 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, const struct link_config_limits *limits, int min_bpp_x16, int max_bpp_x16, - int pipe_bpp, + int bpp_step_x16, int timeslots) { int i, ret; - int output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); - - /* Compressed BPP should be less than the Input DSC bpp */ - max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp - 1)); for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) { if (valid_dsc_bpp[i] < fxp_q4_to_int(min_bpp_x16) || @@ -2116,24 +2112,17 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, */ static int xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, - const struct intel_connector *connector, struct intel_crtc_state *pipe_config, const struct link_config_limits *limits, int min_bpp_x16, int max_bpp_x16, - int pipe_bpp, + int bpp_step_x16, int timeslots) { struct intel_display *display = to_intel_display(intel_dp); - int output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); - int bpp_x16, bpp_step_x16; + int bpp_x16; int ret; - bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); - - /* Compressed BPP should be less than the Input DSC bpp */ - max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); - for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { if (intel_dp->force_dsc_fractional_bpp_en && !fxp_q4_to_frac(bpp_x16)) @@ -2165,9 +2154,10 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, { struct intel_display *display = to_intel_display(intel_dp); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; + int output_bpp; int dsc_min_bpp; int dsc_max_bpp; - int min_bpp_x16, max_bpp_x16; + int min_bpp_x16, max_bpp_x16, bpp_step_x16; int dsc_joiner_max_bpp; int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config); @@ -2182,11 +2172,17 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp); max_bpp_x16 = fxp_q4_from_int(dsc_max_bpp); + bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); + + /* Compressed BPP should be less than the Input DSC bpp */ + output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); + max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); + if (DISPLAY_VER(display) >= 13) - return xelpd_dsc_compute_link_config(intel_dp, connector, pipe_config, limits, - min_bpp_x16, max_bpp_x16, pipe_bpp, timeslots); + return xelpd_dsc_compute_link_config(intel_dp, pipe_config, limits, + min_bpp_x16, max_bpp_x16, bpp_step_x16, timeslots); return icl_dsc_compute_link_config(intel_dp, pipe_config, limits, - min_bpp_x16, max_bpp_x16, pipe_bpp, timeslots); + min_bpp_x16, max_bpp_x16, bpp_step_x16, timeslots); } int intel_dp_dsc_min_src_input_bpc(void) -- cgit v1.2.3-59-g8ed1b From c791c7ebd00ffb91512f387f3ca31f92195c06ea Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:49:59 +0200 Subject: drm/i915/dp: Change icl_dsc_compute_link_config() DSC BPP iteration Instead of iterating the valid BPP array directly, switch to the same approach as xelpd_dsc_compute_link_config(), with a separate function to check if the DSC BPP is valid. This prepares us for unifying the platform specific functions. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/bc1972391041a3ba84b3f68b9c0605ae142611e0.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 898846d61c63..a299b69309dc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2069,6 +2069,26 @@ static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) return fxp_q4_from_int(1) / incr; } +/* Note: This is not universally usable! */ +static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16) +{ + struct intel_display *display = to_intel_display(intel_dp); + int i; + + if (DISPLAY_VER(display) >= 13) + return true; + + if (fxp_q4_to_frac(bpp_x16)) + return false; + + for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) { + if (fxp_q4_to_int(bpp_x16) == valid_dsc_bpp[i]) + return true; + } + + return false; +} + /* * From a list of valid compressed bpps try different compressed bpp and find a * suitable link configuration that can support it. @@ -2082,21 +2102,20 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, int bpp_step_x16, int timeslots) { - int i, ret; + int bpp_x16; + int ret; - for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) { - if (valid_dsc_bpp[i] < fxp_q4_to_int(min_bpp_x16) || - valid_dsc_bpp[i] > fxp_q4_to_int(max_bpp_x16)) + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { + if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16)) continue; ret = dsc_compute_link_config(intel_dp, pipe_config, limits, - valid_dsc_bpp[i] << 4, + bpp_x16, timeslots); if (ret == 0) { - pipe_config->dsc.compressed_bpp_x16 = - fxp_q4_from_int(valid_dsc_bpp[i]); + pipe_config->dsc.compressed_bpp_x16 = bpp_x16; return 0; } } -- cgit v1.2.3-59-g8ed1b From 206914ca6529ea08b2ccb060948959fa837f3f19 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:00 +0200 Subject: drm/i915/dp: Move force_dsc_fractional_bpp_en check to intel_dp_dsc_valid_bpp() Add the fractional DSC BPP force check to intel_dp_dsc_valid_bpp(), and use that in xelpd_dsc_compute_link_config(). This is another step closer towards unifying the platform specific functions. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/2d8cdfef422dc2229d3ead2201bff4a321cbbdd3.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a299b69309dc..2feb686f6419 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2075,8 +2075,12 @@ static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16) struct intel_display *display = to_intel_display(intel_dp); int i; - if (DISPLAY_VER(display) >= 13) + if (DISPLAY_VER(display) >= 13) { + if (intel_dp->force_dsc_fractional_bpp_en && !fxp_q4_to_frac(bpp_x16)) + return false; + return true; + } if (fxp_q4_to_frac(bpp_x16)) return false; @@ -2143,9 +2147,9 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, int ret; for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { - if (intel_dp->force_dsc_fractional_bpp_en && - !fxp_q4_to_frac(bpp_x16)) + if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16)) continue; + ret = dsc_compute_link_config(intel_dp, pipe_config, limits, -- cgit v1.2.3-59-g8ed1b From 9e276d220a650def051a3981a8dfb86c5c23a892 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:01 +0200 Subject: drm/i915/dp: Unify DSC link config functions {icl,xelpd}_dsc_compute_link_config() are now effectively the same, and can be unified to a single platform independent function. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/ca41ebb287fc51e1257d3c2b2790edf2cd661ab3.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 49 ++++----------------------------- 1 file changed, 5 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 2feb686f6419..023466f24f38 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2094,47 +2094,11 @@ static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16) } /* - * From a list of valid compressed bpps try different compressed bpp and find a - * suitable link configuration that can support it. + * Find the max compressed BPP we can find a link configuration for. The BPPs to + * try depend on the source (platform) and sink. */ static int -icl_dsc_compute_link_config(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config, - const struct link_config_limits *limits, - int min_bpp_x16, - int max_bpp_x16, - int bpp_step_x16, - int timeslots) -{ - int bpp_x16; - int ret; - - for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { - if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16)) - continue; - - ret = dsc_compute_link_config(intel_dp, - pipe_config, - limits, - bpp_x16, - timeslots); - if (ret == 0) { - pipe_config->dsc.compressed_bpp_x16 = bpp_x16; - return 0; - } - } - - return -EINVAL; -} - -/* - * From XE_LPD onwards we supports compression bpps in steps of 1 up to - * uncompressed bpp-1. So we start from max compressed bpp and see if any - * link configuration is able to support that compressed bpp, if not we - * step down and check for lower compressed bpp. - */ -static int -xelpd_dsc_compute_link_config(struct intel_dp *intel_dp, +do_dsc_compute_compressed_bpp(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, const struct link_config_limits *limits, int min_bpp_x16, @@ -2201,11 +2165,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); - if (DISPLAY_VER(display) >= 13) - return xelpd_dsc_compute_link_config(intel_dp, pipe_config, limits, - min_bpp_x16, max_bpp_x16, bpp_step_x16, timeslots); - return icl_dsc_compute_link_config(intel_dp, pipe_config, limits, - min_bpp_x16, max_bpp_x16, bpp_step_x16, timeslots); + return do_dsc_compute_compressed_bpp(intel_dp, pipe_config, limits, + min_bpp_x16, max_bpp_x16, bpp_step_x16, timeslots); } int intel_dp_dsc_min_src_input_bpc(void) -- cgit v1.2.3-59-g8ed1b From df64948ec2cecb1dc0747072aca23621ebf80be9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:02 +0200 Subject: drm/i915/dp: Inline do_dsc_compute_compressed_bpp() With just the one platform independent loop left in do_dsc_compute_compressed_bpp(), we don't really need the extra function that is simply becoming increasingly hard to even figure out a decent name for. Just merge the whole thing to dsc_compute_compressed_bpp(). Good riddance to the short lived do_dsc_compute_compressed_bpp(). Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/91ae42cbdffe4938a665667955c577f887b92b9d.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 60 +++++++++++++-------------------- 1 file changed, 23 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 023466f24f38..8175ac0eb802 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2097,41 +2097,6 @@ static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16) * Find the max compressed BPP we can find a link configuration for. The BPPs to * try depend on the source (platform) and sink. */ -static int -do_dsc_compute_compressed_bpp(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config, - const struct link_config_limits *limits, - int min_bpp_x16, - int max_bpp_x16, - int bpp_step_x16, - int timeslots) -{ - struct intel_display *display = to_intel_display(intel_dp); - int bpp_x16; - int ret; - - for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { - if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16)) - continue; - - ret = dsc_compute_link_config(intel_dp, - pipe_config, - limits, - bpp_x16, - timeslots); - if (ret == 0) { - pipe_config->dsc.compressed_bpp_x16 = bpp_x16; - if (intel_dp->force_dsc_fractional_bpp_en && - fxp_q4_to_frac(bpp_x16)) - drm_dbg_kms(display->drm, - "Forcing DSC fractional bpp\n"); - - return 0; - } - } - return -EINVAL; -} - static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, const struct intel_connector *connector, struct intel_crtc_state *pipe_config, @@ -2147,6 +2112,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, int min_bpp_x16, max_bpp_x16, bpp_step_x16; int dsc_joiner_max_bpp; int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config); + int bpp_x16; + int ret; dsc_min_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16); @@ -2165,8 +2132,27 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); - return do_dsc_compute_compressed_bpp(intel_dp, pipe_config, limits, - min_bpp_x16, max_bpp_x16, bpp_step_x16, timeslots); + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { + if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16)) + continue; + + ret = dsc_compute_link_config(intel_dp, + pipe_config, + limits, + bpp_x16, + timeslots); + if (ret == 0) { + pipe_config->dsc.compressed_bpp_x16 = bpp_x16; + if (intel_dp->force_dsc_fractional_bpp_en && + fxp_q4_to_frac(bpp_x16)) + drm_dbg_kms(display->drm, + "Forcing DSC fractional bpp\n"); + + return 0; + } + } + + return -EINVAL; } int intel_dp_dsc_min_src_input_bpc(void) -- cgit v1.2.3-59-g8ed1b From 73ef9abb239bcf2b4ed68d808e0935a4e0ee251b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:03 +0200 Subject: drm/i915/dp: Simplify input BPP checks in intel_dp_dsc_compute_pipe_bpp() Drop the extra local variables and simplify the conditions. We don't have to try to special case the loop condition and break in the validity checks. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/5559b14d6af4e001677f23454d6bd8b3606b3d7a.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8175ac0eb802..22b69c02c13e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2202,8 +2202,6 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, { const struct intel_connector *connector = to_intel_connector(conn_state->connector); - int dsc_max_bpp; - int dsc_min_bpp; u8 dsc_bpc[3] = {}; int forced_bpp, pipe_bpp; int num_bpc, i, ret; @@ -2219,9 +2217,6 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, } } - dsc_max_bpp = limits->pipe.max_bpp; - dsc_min_bpp = limits->pipe.min_bpp; - /* * Get the maximum DSC bpc that will be supported by any valid * link configuration and compressed bpp. @@ -2229,10 +2224,9 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd, dsc_bpc); for (i = 0; i < num_bpc; i++) { pipe_bpp = dsc_bpc[i] * 3; - if (pipe_bpp < dsc_min_bpp) - break; - if (pipe_bpp > dsc_max_bpp) + if (pipe_bpp < limits->pipe.min_bpp || pipe_bpp > limits->pipe.max_bpp) continue; + ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config, limits, pipe_bpp, timeslots); if (ret == 0) { -- cgit v1.2.3-59-g8ed1b From b3f5c960146ab24afe56436389b2dc5cf44e7a36 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:04 +0200 Subject: drm/i915/dp: Use int for compressed BPP in dsc_compute_link_config() Just use ints unless there are actual reasons to do otherwise. Here, there are not. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/b8f9aebc4e40afeed3d723f98cae96c9c927a480.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 22b69c02c13e..27f066ad4073 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1926,7 +1926,7 @@ static bool intel_dp_dsc_supports_format(const struct intel_connector *connector return drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd, sink_dsc_format); } -static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_clock, +static bool is_bw_sufficient_for_dsc_config(int dsc_bpp_x16, u32 link_clock, u32 lane_count, u32 mode_clock, enum intel_output_format output_format, int timeslots) @@ -1934,7 +1934,7 @@ static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_cloc u32 available_bw, required_bw; available_bw = (link_clock * lane_count * timeslots * 16) / 8; - required_bw = compressed_bppx16 * (intel_dp_mode_to_fec_clock(mode_clock)); + required_bw = dsc_bpp_x16 * (intel_dp_mode_to_fec_clock(mode_clock)); return available_bw > required_bw; } @@ -1942,7 +1942,7 @@ static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_cloc static int dsc_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, const struct link_config_limits *limits, - u16 compressed_bppx16, + int dsc_bpp_x16, int timeslots) { const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; @@ -1957,7 +1957,7 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp, for (lane_count = limits->min_lane_count; lane_count <= limits->max_lane_count; lane_count <<= 1) { - if (!is_bw_sufficient_for_dsc_config(compressed_bppx16, link_rate, + if (!is_bw_sufficient_for_dsc_config(dsc_bpp_x16, link_rate, lane_count, adjusted_mode->clock, pipe_config->output_format, timeslots)) -- cgit v1.2.3-59-g8ed1b From 2056f0ad806272363fa7d3754317ef2380c112a1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:05 +0200 Subject: drm/i915/dp: Drop compute_pipe_bpp parameter from intel_dp_dsc_compute_config() The parameter is basically just a proxy for whether the function is being called for DP SST or DP MST. We can figure this out from crtc state. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/82a4b84711b1416bb3382f5d8383fe65ab88159a.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 14 ++++++-------- drivers/gpu/drm/i915/display/intel_dp.h | 3 +-- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 27f066ad4073..adfd1b6d148d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2307,8 +2307,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, const struct link_config_limits *limits, - int timeslots, - bool compute_pipe_bpp) + int timeslots) { struct intel_display *display = to_intel_display(intel_dp); const struct intel_connector *connector = @@ -2316,6 +2315,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config); + bool is_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST); int ret; intel_dp_fec_compute_config(intel_dp, pipe_config); @@ -2324,12 +2324,10 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, return -EINVAL; /* - * compute pipe bpp is set to false for DP MST DSC case - * and compressed_bpp is calculated same time once - * vpci timeslots are allocated, because overall bpp - * calculation procedure is bit different for MST case. + * Link parameters, pipe bpp and compressed bpp have already been + * figured out for DP MST DSC. */ - if (compute_pipe_bpp) { + if (!is_mst) { if (intel_dp_is_edp(intel_dp)) ret = intel_edp_dsc_compute_pipe_bpp(intel_dp, pipe_config, conn_state, limits); @@ -2640,7 +2638,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, return -EINVAL; ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, - conn_state, &limits, 64, true); + conn_state, &limits, 64); if (ret < 0) return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index ffc27f8ad226..9189db4c2594 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -76,8 +76,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, const struct link_config_limits *limits, - int timeslots, - bool recompute_pipe_bpp); + int timeslots); void intel_dp_audio_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index ed7640728b22..04b840070fdb 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -657,7 +657,7 @@ static int mst_stream_compute_config(struct intel_encoder *encoder, ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, conn_state, &limits, - pipe_config->dp_m_n.tu, false); + pipe_config->dp_m_n.tu); } if (ret) -- cgit v1.2.3-59-g8ed1b From cf92a9d4f01d8d63013dc0bdf1fc63ad4f6e7334 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:06 +0200 Subject: drm/i915/dp: Pass connector state all the way to dsc_compute_link_config() Going forward, we'll need the connector state in dsc_compute_link_config(). Pass it along through the chain. Maintain the same parameter order where relevant. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/645d950a80df5fd4441d69aba4893ab263b3e555.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index adfd1b6d148d..e287c3d04339 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1941,6 +1941,7 @@ static bool is_bw_sufficient_for_dsc_config(int dsc_bpp_x16, u32 link_clock, static int dsc_compute_link_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state, const struct link_config_limits *limits, int dsc_bpp_x16, int timeslots) @@ -2098,13 +2099,14 @@ static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16) * try depend on the source (platform) and sink. */ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, - const struct intel_connector *connector, struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state, const struct link_config_limits *limits, int pipe_bpp, int timeslots) { struct intel_display *display = to_intel_display(intel_dp); + const struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int output_bpp; int dsc_min_bpp; @@ -2138,6 +2140,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, ret = dsc_compute_link_config(intel_dp, pipe_config, + conn_state, limits, bpp_x16, timeslots); @@ -2209,7 +2212,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, forced_bpp = intel_dp_force_dsc_pipe_bpp(intel_dp, limits); if (forced_bpp) { - ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config, + ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state, limits, forced_bpp, timeslots); if (ret == 0) { pipe_config->pipe_bpp = forced_bpp; @@ -2227,7 +2230,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, if (pipe_bpp < limits->pipe.min_bpp || pipe_bpp > limits->pipe.max_bpp) continue; - ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config, + ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state, limits, pipe_bpp, timeslots); if (ret == 0) { pipe_config->pipe_bpp = pipe_bpp; -- cgit v1.2.3-59-g8ed1b From 67782bf6e8a6289996bbc3ce7138c30ff72ee458 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2025 14:50:07 +0200 Subject: drm/i915/mst: Convert intel_dp_mtp_tu_compute_config() to .4 format Move towards always using the fxp q4 or .4 fixed point format for compressed bpp. We'll need to pass the more accurate bpp to this function later on. Always use _x16 naming for variables that are in .4 fixed point for clarity. Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/887306a47ce4550226f5d54178f667a52840a11c.1738327620.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 4 +-- drivers/gpu/drm/i915/display/intel_dp_mst.c | 52 +++++++++++++++++------------ drivers/gpu/drm/i915/display/intel_dp_mst.h | 2 +- 3 files changed, 33 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e287c3d04339..e9a9f1f8d353 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2616,8 +2616,8 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, ret = intel_dp_mtp_tu_compute_config(intel_dp, pipe_config, conn_state, - pipe_config->pipe_bpp, - pipe_config->pipe_bpp, + fxp_q4_from_int(pipe_config->pipe_bpp), + fxp_q4_from_int(pipe_config->pipe_bpp), 0, false); if (ret) dsc_needed = true; diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 04b840070fdb..7e58b9464a24 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -212,7 +212,7 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, - int min_bpp, int max_bpp, int step, bool dsc) + int min_bpp_x16, int max_bpp_x16, int bpp_step_x16, bool dsc) { struct intel_display *display = to_intel_display(intel_dp); struct drm_atomic_state *state = crtc_state->uapi.state; @@ -222,9 +222,14 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; bool is_mst = intel_dp->is_mst; - int bpp, slots = -EINVAL; + int bpp_x16, slots = -EINVAL; int dsc_slice_count = 0; - int max_dpt_bpp; + int max_dpt_bpp_x16; + + /* shouldn't happen, sanity check */ + drm_WARN_ON(display->drm, !dsc && (fxp_q4_to_frac(min_bpp_x16) || + fxp_q4_to_frac(max_bpp_x16) || + fxp_q4_to_frac(bpp_step_x16))); if (is_mst) { mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); @@ -242,15 +247,15 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, crtc_state->fec_enable = !intel_dp_is_uhbr(crtc_state); } - max_dpt_bpp = intel_dp_mst_max_dpt_bpp(crtc_state, dsc); - if (max_bpp > max_dpt_bpp) { - drm_dbg_kms(display->drm, "Limiting bpp to max DPT bpp (%d -> %d)\n", - max_bpp, max_dpt_bpp); - max_bpp = max_dpt_bpp; + max_dpt_bpp_x16 = fxp_q4_from_int(intel_dp_mst_max_dpt_bpp(crtc_state, dsc)); + if (max_bpp_x16 > max_dpt_bpp_x16) { + drm_dbg_kms(display->drm, "Limiting bpp to max DPT bpp (" FXP_Q4_FMT " -> " FXP_Q4_FMT ")\n", + FXP_Q4_ARGS(max_bpp_x16), FXP_Q4_ARGS(max_dpt_bpp_x16)); + max_bpp_x16 = max_dpt_bpp_x16; } - drm_dbg_kms(display->drm, "Looking for slots in range min bpp %d max bpp %d\n", - min_bpp, max_bpp); + drm_dbg_kms(display->drm, "Looking for slots in range min bpp " FXP_Q4_FMT " max bpp " FXP_Q4_FMT "\n", + FXP_Q4_ARGS(min_bpp_x16), FXP_Q4_ARGS(max_bpp_x16)); if (dsc) { dsc_slice_count = intel_dp_mst_dsc_get_slice_count(connector, crtc_state); @@ -261,14 +266,15 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, } } - for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) { + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { int local_bw_overhead; int link_bpp_x16; - drm_dbg_kms(display->drm, "Trying bpp %d\n", bpp); + drm_dbg_kms(display->drm, "Trying bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(bpp_x16)); - link_bpp_x16 = fxp_q4_from_int(dsc ? bpp : - intel_dp_output_bpp(crtc_state->output_format, bpp)); + link_bpp_x16 = dsc ? bpp_x16 : + fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format, + fxp_q4_to_int(bpp_x16))); local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state, false, dsc_slice_count, link_bpp_x16); @@ -356,12 +362,12 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, } if (!dsc) - crtc_state->pipe_bpp = bpp; + crtc_state->pipe_bpp = fxp_q4_to_int(bpp_x16); else - crtc_state->dsc.compressed_bpp_x16 = fxp_q4_from_int(bpp); + crtc_state->dsc.compressed_bpp_x16 = bpp_x16; - drm_dbg_kms(display->drm, "Got %d slots for pipe bpp %d dsc %d\n", - slots, bpp, dsc); + drm_dbg_kms(display->drm, "Got %d slots for pipe bpp " FXP_Q4_FMT " dsc %d\n", + slots, FXP_Q4_ARGS(bpp_x16), dsc); return 0; } @@ -379,9 +385,9 @@ static int mst_stream_compute_link_config(struct intel_dp *intel_dp, * YUV420 is only half of the pipe bpp value. */ return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, - fxp_q4_to_int(limits->link.min_bpp_x16), - fxp_q4_to_int(limits->link.max_bpp_x16), - 2 * 3, false); + limits->link.min_bpp_x16, + limits->link.max_bpp_x16, + fxp_q4_from_int(2 * 3), false); } static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, @@ -435,7 +441,9 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, crtc_state->port_clock = limits->max_rate; return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, - min_compressed_bpp, max_compressed_bpp, 1, true); + fxp_q4_from_int(min_compressed_bpp), + fxp_q4_from_int(max_compressed_bpp), + fxp_q4_from_int(1), true); } static int mst_stream_update_slots(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h index a713a1c10154..c1bbfeb02ca9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.h +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h @@ -34,6 +34,6 @@ bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp); int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, - int min_bpp, int max_bpp, int step, bool dsc); + int min_bpp_x16, int max_bpp_x16, int bpp_step_x16, bool dsc); #endif /* __INTEL_DP_MST_H__ */ -- cgit v1.2.3-59-g8ed1b From ae5d9cde9b762fd4b7259e1f93a94e0c7f04681c Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 31 Jan 2025 14:39:08 -0800 Subject: drm/xe: Remove xe_dummy_exit() Since commit 014125c64d09 ("drm/xe: Support 'nomodeset' kernel command-line option") the dummy exit is not needed anymore since the caller check for a NULL pointer. Drop it. Reviewed-by: Raag Jadav Link: https://patchwork.freedesktop.org/patch/msgid/20250131223908.4147195-1-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_module.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c index 07b27114be9a..7185a2cdf6e3 100644 --- a/drivers/gpu/drm/xe/xe_module.c +++ b/drivers/gpu/drm/xe/xe_module.c @@ -77,10 +77,6 @@ struct init_funcs { void (*exit)(void); }; -static void xe_dummy_exit(void) -{ -} - static const struct init_funcs init_funcs[] = { { .init = xe_check_nomodeset, @@ -103,7 +99,6 @@ static const struct init_funcs init_funcs[] = { }, { .init = xe_pm_module_init, - .exit = xe_dummy_exit, }, }; -- cgit v1.2.3-59-g8ed1b From ff48e05d8d1eefbdeb4504c0275c78654b858046 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:25 -0800 Subject: drm/xe/pxp: Initialize PXP structure and KCR reg As the first step towards adding PXP support, hook in the PXP init function, allocate the PXP structure and initialize the KCR register to allow PXP HWDRM sessions. v2: remove unneeded includes, free PXP memory on error (John) Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-2-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/Makefile | 1 + .../gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h | 4 +- drivers/gpu/drm/xe/regs/xe_pxp_regs.h | 17 ++++ drivers/gpu/drm/xe/xe_device.c | 6 ++ drivers/gpu/drm/xe/xe_device_types.h | 8 +- drivers/gpu/drm/xe/xe_pci.c | 2 + drivers/gpu/drm/xe/xe_pxp.c | 107 +++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp.h | 13 +++ drivers/gpu/drm/xe/xe_pxp_types.h | 26 +++++ 9 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/xe/regs/xe_pxp_regs.h create mode 100644 drivers/gpu/drm/xe/xe_pxp.c create mode 100644 drivers/gpu/drm/xe/xe_pxp.h create mode 100644 drivers/gpu/drm/xe/xe_pxp_types.h (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index e6960db45b73..708e9f0108dc 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -87,6 +87,7 @@ xe-y += xe_bb.o \ xe_preempt_fence.o \ xe_pt.o \ xe_pt_walk.o \ + xe_pxp.o \ xe_query.o \ xe_range_fence.o \ xe_reg_sr.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h b/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h index 5dfc587c8237..419e8e926f00 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h @@ -10,9 +10,9 @@ #include struct drm_gem_object; -struct intel_pxp; +struct xe_pxp; -static inline int intel_pxp_key_check(struct intel_pxp *pxp, +static inline int intel_pxp_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj, bool assign) { diff --git a/drivers/gpu/drm/xe/regs/xe_pxp_regs.h b/drivers/gpu/drm/xe/regs/xe_pxp_regs.h new file mode 100644 index 000000000000..d67cf210d23d --- /dev/null +++ b/drivers/gpu/drm/xe/regs/xe_pxp_regs.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright(c) 2024, Intel Corporation. All rights reserved. + */ + +#ifndef __XE_PXP_REGS_H__ +#define __XE_PXP_REGS_H__ + +#include "regs/xe_regs.h" + +/* The following registers are only valid on platforms with a media GT */ + +/* KCR enable/disable control */ +#define KCR_INIT XE_REG(0x3860f0) +#define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14) + +#endif /* __XE_PXP_REGS_H__ */ diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 8a2763e8a6e2..f30f8f668dee 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -50,6 +50,7 @@ #include "xe_pcode.h" #include "xe_pm.h" #include "xe_pmu.h" +#include "xe_pxp.h" #include "xe_query.h" #include "xe_sriov.h" #include "xe_survivability_mode.h" @@ -861,6 +862,11 @@ int xe_device_probe(struct xe_device *xe) if (err) goto err_fini_oa; + /* A PXP init failure is not fatal */ + err = xe_pxp_init(xe); + if (err && err != -EOPNOTSUPP) + drm_err(&xe->drm, "PXP initialization failed: %pe\n", ERR_PTR(err)); + err = drm_dev_register(&xe->drm, 0); if (err) goto err_fini_display; diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 89f532b67bc4..c0e886bac183 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -36,6 +36,7 @@ struct xe_ggtt; struct xe_pat_ops; +struct xe_pxp; #define XE_BO_INVALID_OFFSET LONG_MAX @@ -307,6 +308,8 @@ struct xe_device { u8 has_heci_gscfi:1; /** @info.has_llc: Device has a shared CPU+GPU last level cache */ u8 has_llc:1; + /** @info.has_pxp: Device has PXP support */ + u8 has_pxp:1; /** @info.has_range_tlb_invalidation: Has range based TLB invalidations */ u8 has_range_tlb_invalidation:1; /** @info.has_sriov: Supports SR-IOV */ @@ -508,6 +511,9 @@ struct xe_device { /** @oa: oa observation subsystem */ struct xe_oa oa; + /** @pxp: Encapsulate Protected Xe Path support */ + struct xe_pxp *pxp; + /** @needs_flr_on_fini: requests function-reset on fini */ bool needs_flr_on_fini; @@ -583,8 +589,6 @@ struct xe_device { unsigned int czclk_freq; unsigned int fsb_freq, mem_freq, is_ddr3; }; - - void *pxp; #endif }; diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index f05cf26a088c..0a6e58d55682 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -62,6 +62,7 @@ struct xe_device_desc { u8 has_heci_gscfi:1; u8 has_heci_cscfi:1; u8 has_llc:1; + u8 has_pxp:1; u8 has_sriov:1; u8 skip_guc_pc:1; u8 skip_mtcfg:1; @@ -618,6 +619,7 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.has_heci_gscfi = desc->has_heci_gscfi; xe->info.has_heci_cscfi = desc->has_heci_cscfi; xe->info.has_llc = desc->has_llc; + xe->info.has_pxp = desc->has_pxp; xe->info.has_sriov = desc->has_sriov; xe->info.skip_guc_pc = desc->skip_guc_pc; xe->info.skip_mtcfg = desc->skip_mtcfg; diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c new file mode 100644 index 000000000000..1a4d12d37d96 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright(c) 2024 Intel Corporation. + */ + +#include "xe_pxp.h" + +#include + +#include "xe_device_types.h" +#include "xe_force_wake.h" +#include "xe_gt.h" +#include "xe_gt_types.h" +#include "xe_mmio.h" +#include "xe_pxp_types.h" +#include "xe_uc_fw.h" +#include "regs/xe_pxp_regs.h" + +/** + * DOC: PXP + * + * PXP (Protected Xe Path) allows execution and flip to display of protected + * (i.e. encrypted) objects. This feature is currently only supported in + * integrated parts. + */ + +static bool pxp_is_supported(const struct xe_device *xe) +{ + return xe->info.has_pxp && IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY); +} + +static int kcr_pxp_set_status(const struct xe_pxp *pxp, bool enable) +{ + u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) : + _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES); + unsigned int fw_ref; + + fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) + return -EIO; + + xe_mmio_write32(&pxp->gt->mmio, KCR_INIT, val); + xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref); + + return 0; +} + +static int kcr_pxp_enable(const struct xe_pxp *pxp) +{ + return kcr_pxp_set_status(pxp, true); +} + +/** + * xe_pxp_init - initialize PXP support + * @xe: the xe_device structure + * + * Initialize the HW state and allocate the objects required for PXP support. + * Note that some of the requirement for PXP support (GSC proxy init, HuC auth) + * are performed asynchronously as part of the GSC init. PXP can only be used + * after both this function and the async worker have completed. + * + * Returns -EOPNOTSUPP if PXP is not supported, 0 if PXP initialization is + * successful, other errno value if there is an error during the init. + */ +int xe_pxp_init(struct xe_device *xe) +{ + struct xe_gt *gt = xe->tiles[0].media_gt; + struct xe_pxp *pxp; + int err; + + if (!pxp_is_supported(xe)) + return -EOPNOTSUPP; + + /* we only support PXP on single tile devices with a media GT */ + if (xe->info.tile_count > 1 || !gt) + return -EOPNOTSUPP; + + /* The GSCCS is required for submissions to the GSC FW */ + if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0))) + return -EOPNOTSUPP; + + /* PXP requires both GSC and HuC firmwares to be available */ + if (!xe_uc_fw_is_loadable(>->uc.gsc.fw) || + !xe_uc_fw_is_loadable(>->uc.huc.fw)) { + drm_info(&xe->drm, "skipping PXP init due to missing FW dependencies"); + return -EOPNOTSUPP; + } + + pxp = drmm_kzalloc(&xe->drm, sizeof(struct xe_pxp), GFP_KERNEL); + if (!pxp) + return -ENOMEM; + + pxp->xe = xe; + pxp->gt = gt; + + err = kcr_pxp_enable(pxp); + if (err) + goto out_free; + + xe->pxp = pxp; + + return 0; + +out_free: + drmm_kfree(&xe->drm, pxp); + return err; +} diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h new file mode 100644 index 000000000000..00f5e688c0d9 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright(c) 2024, Intel Corporation. All rights reserved. + */ + +#ifndef __XE_PXP_H__ +#define __XE_PXP_H__ + +struct xe_device; + +int xe_pxp_init(struct xe_device *xe); + +#endif /* __XE_PXP_H__ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h new file mode 100644 index 000000000000..4639cf49d267 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright(c) 2024, Intel Corporation. All rights reserved. + */ + +#ifndef __XE_PXP_TYPES_H__ +#define __XE_PXP_TYPES_H__ + +struct xe_device; +struct xe_gt; + +/** + * struct xe_pxp - pxp state + */ +struct xe_pxp { + /** @xe: Backpoiner to the xe_device struct */ + struct xe_device *xe; + + /** + * @gt: pointer to the gt that owns the submission-side of PXP + * (VDBOX, KCR and GSC) + */ + struct xe_gt *gt; +}; + +#endif /* __XE_PXP_TYPES_H__ */ -- cgit v1.2.3-59-g8ed1b From dcdd6b84d9acaa0794c29de7024cfdb20cfd7b92 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:26 -0800 Subject: drm/xe/pxp: Allocate PXP execution resources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PXP requires submissions to the HW for the following operations 1) Key invalidation, done via the VCS engine 2) Communication with the GSC FW for session management, done via the GSCCS. Key invalidation submissions are serialized (only 1 termination can be serviced at a given time) and done via GGTT, so we can allocate a simple BO and a kernel queue for it. Submissions for session management are tied to a PXP client (identified by a unique host_session_id); from the GSC POV this is a user-accessible construct, so all related submission must be done via PPGTT. The driver does not currently support PPGTT submission from within the kernel, so to add this support, the following changes have been included: - a new type of kernel-owned VM (marked as GSC), required to ensure we don't use fault mode on the engine and to mark the different lock usage with lockdep. - a new function to map a BO into a VM from within the kernel. v2: improve comments and function name, remove unneeded include (John) v3: fix variable/function names in documentation Signed-off-by: Daniele Ceraolo Spurio Cc: Matthew Brost Cc: Thomas Hellström Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-3-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h | 7 + drivers/gpu/drm/xe/xe_exec_queue.c | 3 + drivers/gpu/drm/xe/xe_pxp.c | 23 ++- drivers/gpu/drm/xe/xe_pxp_submit.c | 199 ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp_submit.h | 14 ++ drivers/gpu/drm/xe/xe_pxp_types.h | 48 +++++++ drivers/gpu/drm/xe/xe_vm.c | 119 +++++++++++++-- drivers/gpu/drm/xe/xe_vm.h | 6 + drivers/gpu/drm/xe/xe_vm_types.h | 1 + 10 files changed, 410 insertions(+), 11 deletions(-) create mode 100644 drivers/gpu/drm/xe/xe_pxp_submit.c create mode 100644 drivers/gpu/drm/xe/xe_pxp_submit.h (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 708e9f0108dc..720d13c16fa5 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -88,6 +88,7 @@ xe-y += xe_bb.o \ xe_pt.o \ xe_pt_walk.o \ xe_pxp.o \ + xe_pxp_submit.o \ xe_query.o \ xe_range_fence.o \ xe_reg_sr.o \ diff --git a/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h b/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h index 57520809e48d..f3c4cf10ba20 100644 --- a/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h +++ b/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h @@ -6,6 +6,7 @@ #ifndef _ABI_GSC_PXP_COMMANDS_ABI_H #define _ABI_GSC_PXP_COMMANDS_ABI_H +#include #include /* Heci client ID for PXP commands */ @@ -13,6 +14,12 @@ #define PXP_APIVER(x, y) (((x) & 0xFFFF) << 16 | ((y) & 0xFFFF)) +/* + * A PXP sub-section in an HECI packet can be up to 64K big in each direction. + * This does not include the top-level GSC header. + */ +#define PXP_MAX_PACKET_SIZE SZ_64K + /* * there are a lot of status codes for PXP, but we only define the cross-API * common ones that we actually can handle in the kernel driver. Other failure diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 7e1abbbfba12..252bfa11cae9 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -153,6 +153,9 @@ struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *v struct xe_exec_queue *q; int err; + /* VMs for GSCCS queues (and only those) must have the XE_VM_FLAG_GSC flag */ + xe_assert(xe, !vm || (!!(vm->flags & XE_VM_FLAG_GSC) == !!(hwe->engine_id == XE_HW_ENGINE_GSCCS0))); + q = __xe_exec_queue_alloc(xe, vm, logical_mask, width, hwe, flags, extensions); if (IS_ERR(q)) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 1a4d12d37d96..89d71a69cdff 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -12,6 +12,7 @@ #include "xe_gt.h" #include "xe_gt_types.h" #include "xe_mmio.h" +#include "xe_pxp_submit.h" #include "xe_pxp_types.h" #include "xe_uc_fw.h" #include "regs/xe_pxp_regs.h" @@ -50,6 +51,20 @@ static int kcr_pxp_enable(const struct xe_pxp *pxp) return kcr_pxp_set_status(pxp, true); } +static int kcr_pxp_disable(const struct xe_pxp *pxp) +{ + return kcr_pxp_set_status(pxp, false); +} + +static void pxp_fini(void *arg) +{ + struct xe_pxp *pxp = arg; + + xe_pxp_destroy_execution_resources(pxp); + + /* no need to explicitly disable KCR since we're going to do an FLR */ +} + /** * xe_pxp_init - initialize PXP support * @xe: the xe_device structure @@ -97,10 +112,16 @@ int xe_pxp_init(struct xe_device *xe) if (err) goto out_free; + err = xe_pxp_allocate_execution_resources(pxp); + if (err) + goto out_kcr_disable; + xe->pxp = pxp; - return 0; + return devm_add_action_or_reset(xe->drm.dev, pxp_fini, pxp); +out_kcr_disable: + kcr_pxp_disable(pxp); out_free: drmm_kfree(&xe->drm, pxp); return err; diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.c b/drivers/gpu/drm/xe/xe_pxp_submit.c new file mode 100644 index 000000000000..52a6143b5ebe --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pxp_submit.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright(c) 2024 Intel Corporation. + */ + +#include "xe_pxp_submit.h" + +#include + +#include "xe_device_types.h" +#include "xe_bo.h" +#include "xe_exec_queue.h" +#include "xe_gsc_submit.h" +#include "xe_gt.h" +#include "xe_pxp_types.h" +#include "xe_vm.h" + +/* + * The VCS is used for kernel-owned GGTT submissions to issue key termination. + * Terminations are serialized, so we only need a single queue and a single + * batch. + */ +static int allocate_vcs_execution_resources(struct xe_pxp *pxp) +{ + struct xe_gt *gt = pxp->gt; + struct xe_device *xe = pxp->xe; + struct xe_tile *tile = gt_to_tile(gt); + struct xe_hw_engine *hwe; + struct xe_exec_queue *q; + struct xe_bo *bo; + int err; + + hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_VIDEO_DECODE, 0, true); + if (!hwe) + return -ENODEV; + + q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), 1, hwe, + EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_PERMANENT, 0); + if (IS_ERR(q)) + return PTR_ERR(q); + + /* + * Each termination is 16 DWORDS, so 4K is enough to contain a + * termination for each sessions. + */ + bo = xe_bo_create_pin_map(xe, tile, 0, SZ_4K, ttm_bo_type_kernel, + XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_GGTT); + if (IS_ERR(bo)) { + err = PTR_ERR(bo); + goto out_queue; + } + + pxp->vcs_exec.q = q; + pxp->vcs_exec.bo = bo; + + return 0; + +out_queue: + xe_exec_queue_put(q); + return err; +} + +static void destroy_vcs_execution_resources(struct xe_pxp *pxp) +{ + if (pxp->vcs_exec.bo) + xe_bo_unpin_map_no_vm(pxp->vcs_exec.bo); + + if (pxp->vcs_exec.q) + xe_exec_queue_put(pxp->vcs_exec.q); +} + +#define PXP_BB_SIZE XE_PAGE_SIZE +static int allocate_gsc_client_resources(struct xe_gt *gt, + struct xe_pxp_gsc_client_resources *gsc_res, + size_t inout_size) +{ + struct xe_tile *tile = gt_to_tile(gt); + struct xe_device *xe = tile_to_xe(tile); + struct xe_hw_engine *hwe; + struct xe_vm *vm; + struct xe_bo *bo; + struct xe_exec_queue *q; + struct dma_fence *fence; + long timeout; + int err = 0; + + hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_OTHER, 0, true); + + /* we shouldn't reach here if the GSC engine is not available */ + xe_assert(xe, hwe); + + /* PXP instructions must be issued from PPGTT */ + vm = xe_vm_create(xe, XE_VM_FLAG_GSC); + if (IS_ERR(vm)) + return PTR_ERR(vm); + + /* We allocate a single object for the batch and the in/out memory */ + xe_vm_lock(vm, false); + bo = xe_bo_create_pin_map(xe, tile, vm, PXP_BB_SIZE + inout_size * 2, + ttm_bo_type_kernel, + XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_NEEDS_UC); + xe_vm_unlock(vm); + if (IS_ERR(bo)) { + err = PTR_ERR(bo); + goto vm_out; + } + + fence = xe_vm_bind_kernel_bo(vm, bo, NULL, 0, XE_CACHE_WB); + if (IS_ERR(fence)) { + err = PTR_ERR(fence); + goto bo_out; + } + + timeout = dma_fence_wait_timeout(fence, false, HZ); + dma_fence_put(fence); + if (timeout <= 0) { + err = timeout ?: -ETIME; + goto bo_out; + } + + q = xe_exec_queue_create(xe, vm, BIT(hwe->logical_instance), 1, hwe, + EXEC_QUEUE_FLAG_KERNEL | + EXEC_QUEUE_FLAG_PERMANENT, 0); + if (IS_ERR(q)) { + err = PTR_ERR(q); + goto bo_out; + } + + gsc_res->vm = vm; + gsc_res->bo = bo; + gsc_res->inout_size = inout_size; + gsc_res->batch = IOSYS_MAP_INIT_OFFSET(&bo->vmap, 0); + gsc_res->msg_in = IOSYS_MAP_INIT_OFFSET(&bo->vmap, PXP_BB_SIZE); + gsc_res->msg_out = IOSYS_MAP_INIT_OFFSET(&bo->vmap, PXP_BB_SIZE + inout_size); + gsc_res->q = q; + + /* initialize host-session-handle (for all Xe-to-gsc-firmware PXP cmds) */ + gsc_res->host_session_handle = xe_gsc_create_host_session_id(); + + return 0; + +bo_out: + xe_bo_unpin_map_no_vm(bo); +vm_out: + xe_vm_close_and_put(vm); + + return err; +} + +static void destroy_gsc_client_resources(struct xe_pxp_gsc_client_resources *gsc_res) +{ + if (!gsc_res->q) + return; + + xe_exec_queue_put(gsc_res->q); + xe_bo_unpin_map_no_vm(gsc_res->bo); + xe_vm_close_and_put(gsc_res->vm); +} + +/** + * xe_pxp_allocate_execution_resources - Allocate PXP submission objects + * @pxp: the xe_pxp structure + * + * Allocates exec_queues objects for VCS and GSCCS submission. The GSCCS + * submissions are done via PPGTT, so this function allocates a VM for it and + * maps the object into it. + * + * Returns 0 if the allocation and mapping is successful, an errno value + * otherwise. + */ +int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp) +{ + int err; + + err = allocate_vcs_execution_resources(pxp); + if (err) + return err; + + /* + * PXP commands can require a lot of BO space (see PXP_MAX_PACKET_SIZE), + * but we currently only support a subset of commands that are small + * (< 20 dwords), so a single page is enough for now. + */ + err = allocate_gsc_client_resources(pxp->gt, &pxp->gsc_res, XE_PAGE_SIZE); + if (err) + goto destroy_vcs_context; + + return 0; + +destroy_vcs_context: + destroy_vcs_execution_resources(pxp); + return err; +} + +void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp) +{ + destroy_gsc_client_resources(&pxp->gsc_res); + destroy_vcs_execution_resources(pxp); +} diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.h b/drivers/gpu/drm/xe/xe_pxp_submit.h new file mode 100644 index 000000000000..fd21ac935be1 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pxp_submit.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright(c) 2024, Intel Corporation. All rights reserved. + */ + +#ifndef __XE_PXP_SUBMIT_H__ +#define __XE_PXP_SUBMIT_H__ + +struct xe_pxp; + +int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp); +void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp); + +#endif /* __XE_PXP_SUBMIT_H__ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h index 4639cf49d267..0f86b50756cc 100644 --- a/drivers/gpu/drm/xe/xe_pxp_types.h +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -6,8 +6,45 @@ #ifndef __XE_PXP_TYPES_H__ #define __XE_PXP_TYPES_H__ +#include +#include + +struct xe_bo; +struct xe_exec_queue; struct xe_device; struct xe_gt; +struct xe_vm; + +/** + * struct xe_pxp_gsc_client_resources - resources for GSC submission by a PXP + * client. The GSC FW supports multiple GSC client active at the same time. + */ +struct xe_pxp_gsc_client_resources { + /** + * @host_session_handle: handle used to identify the client in messages + * sent to the GSC firmware. + */ + u64 host_session_handle; + /** @vm: VM used for PXP submissions to the GSCCS */ + struct xe_vm *vm; + /** @q: GSCCS exec queue for PXP submissions */ + struct xe_exec_queue *q; + + /** + * @bo: BO used for submissions to the GSCCS and GSC FW. It includes + * space for the GSCCS batch and the input/output buffers read/written + * by the FW + */ + struct xe_bo *bo; + /** @inout_size: size of each of the msg_in/out sections individually */ + u32 inout_size; + /** @batch: iosys_map to the batch memory within the BO */ + struct iosys_map batch; + /** @msg_in: iosys_map to the input memory within the BO */ + struct iosys_map msg_in; + /** @msg_out: iosys_map to the output memory within the BO */ + struct iosys_map msg_out; +}; /** * struct xe_pxp - pxp state @@ -21,6 +58,17 @@ struct xe_pxp { * (VDBOX, KCR and GSC) */ struct xe_gt *gt; + + /** @vcs_exec: kernel-owned objects for PXP submissions to the VCS */ + struct { + /** @vcs_exec.q: kernel-owned VCS exec queue used for PXP terminations */ + struct xe_exec_queue *q; + /** @vcs_exec.bo: BO used for submissions to the VCS */ + struct xe_bo *bo; + } vcs_exec; + + /** @gsc_res: kernel-owned objects for PXP submissions to the GSCCS */ + struct xe_pxp_gsc_client_resources gsc_res; }; #endif /* __XE_PXP_TYPES_H__ */ diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 690330352d4c..b9270d059e18 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1382,6 +1382,12 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) struct xe_tile *tile; u8 id; + /* + * Since the GSCCS is not user-accessible, we don't expect a GSC VM to + * ever be in faulting mode. + */ + xe_assert(xe, !((flags & XE_VM_FLAG_GSC) && (flags & XE_VM_FLAG_FAULT_MODE))); + vm = kzalloc(sizeof(*vm), GFP_KERNEL); if (!vm) return ERR_PTR(-ENOMEM); @@ -1392,7 +1398,21 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) vm->flags = flags; - init_rwsem(&vm->lock); + /** + * GSC VMs are kernel-owned, only used for PXP ops and can sometimes be + * manipulated under the PXP mutex. However, the PXP mutex can be taken + * under a user-VM lock when the PXP session is started at exec_queue + * creation time. Those are different VMs and therefore there is no risk + * of deadlock, but we need to tell lockdep that this is the case or it + * will print a warning. + */ + if (flags & XE_VM_FLAG_GSC) { + static struct lock_class_key gsc_vm_key; + + __init_rwsem(&vm->lock, "gsc_vm", &gsc_vm_key); + } else { + init_rwsem(&vm->lock); + } mutex_init(&vm->snap_mutex); INIT_LIST_HEAD(&vm->rebind_list); @@ -2668,11 +2688,10 @@ static void vm_bind_ioctl_ops_fini(struct xe_vm *vm, struct xe_vma_ops *vops, for (i = 0; i < vops->num_syncs; i++) xe_sync_entry_signal(vops->syncs + i, fence); xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence); - dma_fence_put(fence); } -static int vm_bind_ioctl_ops_execute(struct xe_vm *vm, - struct xe_vma_ops *vops) +static struct dma_fence *vm_bind_ioctl_ops_execute(struct xe_vm *vm, + struct xe_vma_ops *vops) { struct drm_exec exec; struct dma_fence *fence; @@ -2685,21 +2704,21 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm, drm_exec_until_all_locked(&exec) { err = vm_bind_ioctl_ops_lock_and_prep(&exec, vm, vops); drm_exec_retry_on_contention(&exec); - if (err) + if (err) { + fence = ERR_PTR(err); goto unlock; + } fence = ops_execute(vm, vops); - if (IS_ERR(fence)) { - err = PTR_ERR(fence); + if (IS_ERR(fence)) goto unlock; - } vm_bind_ioctl_ops_fini(vm, vops, fence); } unlock: drm_exec_fini(&exec); - return err; + return fence; } ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_execute, ERRNO); @@ -2931,6 +2950,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) struct xe_sync_entry *syncs = NULL; struct drm_xe_vm_bind_op *bind_ops; struct xe_vma_ops vops; + struct dma_fence *fence; int err; int i; @@ -3095,7 +3115,11 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (err) goto unwind_ops; - err = vm_bind_ioctl_ops_execute(vm, &vops); + fence = vm_bind_ioctl_ops_execute(vm, &vops); + if (IS_ERR(fence)) + err = PTR_ERR(fence); + else + dma_fence_put(fence); unwind_ops: if (err && err != -ENODATA) @@ -3129,6 +3153,81 @@ free_objs: return err; } +/** + * xe_vm_bind_kernel_bo - bind a kernel BO to a VM + * @vm: VM to bind the BO to + * @bo: BO to bind + * @q: exec queue to use for the bind (optional) + * @addr: address at which to bind the BO + * @cache_lvl: PAT cache level to use + * + * Execute a VM bind map operation on a kernel-owned BO to bind it into a + * kernel-owned VM. + * + * Returns a dma_fence to track the binding completion if the job to do so was + * successfully submitted, an error pointer otherwise. + */ +struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, + struct xe_exec_queue *q, u64 addr, + enum xe_cache_level cache_lvl) +{ + struct xe_vma_ops vops; + struct drm_gpuva_ops *ops = NULL; + struct dma_fence *fence; + int err; + + xe_bo_get(bo); + xe_vm_get(vm); + if (q) + xe_exec_queue_get(q); + + down_write(&vm->lock); + + xe_vma_ops_init(&vops, vm, q, NULL, 0); + + ops = vm_bind_ioctl_ops_create(vm, bo, 0, addr, bo->size, + DRM_XE_VM_BIND_OP_MAP, 0, 0, + vm->xe->pat.idx[cache_lvl]); + if (IS_ERR(ops)) { + err = PTR_ERR(ops); + goto release_vm_lock; + } + + err = vm_bind_ioctl_ops_parse(vm, ops, &vops); + if (err) + goto release_vm_lock; + + xe_assert(vm->xe, !list_empty(&vops.list)); + + err = xe_vma_ops_alloc(&vops, false); + if (err) + goto unwind_ops; + + fence = vm_bind_ioctl_ops_execute(vm, &vops); + if (IS_ERR(fence)) + err = PTR_ERR(fence); + +unwind_ops: + if (err && err != -ENODATA) + vm_bind_ioctl_ops_unwind(vm, &ops, 1); + + xe_vma_ops_fini(&vops); + drm_gpuva_ops_free(&vm->gpuvm, ops); + +release_vm_lock: + up_write(&vm->lock); + + if (q) + xe_exec_queue_put(q); + xe_vm_put(vm); + xe_bo_put(bo); + + if (err) + fence = ERR_PTR(err); + + return fence; +} + /** * xe_vm_lock() - Lock the vm's dma_resv object * @vm: The struct xe_vm whose lock is to be locked diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 23adb7442881..0a2fa6c0815b 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -18,6 +18,8 @@ struct drm_file; struct ttm_buffer_object; +struct dma_fence; + struct xe_exec_queue; struct xe_file; struct xe_sync_entry; @@ -247,6 +249,10 @@ int xe_vm_lock_vma(struct drm_exec *exec, struct xe_vma *vma); int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec, unsigned int num_fences); +struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, + struct xe_exec_queue *q, u64 addr, + enum xe_cache_level cache_lvl); + /** * xe_vm_resv() - Return's the vm's reservation object * @vm: The vm diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 7f9a303e51d8..52467b9b5348 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -164,6 +164,7 @@ struct xe_vm { #define XE_VM_FLAG_BANNED BIT(5) #define XE_VM_FLAG_TILE_ID(flags) FIELD_GET(GENMASK(7, 6), flags) #define XE_VM_FLAG_SET_TILE_ID(tile) FIELD_PREP(GENMASK(7, 6), (tile)->id) +#define XE_VM_FLAG_GSC BIT(8) unsigned long flags; /** @composite_fence_ctx: context composite fence */ -- cgit v1.2.3-59-g8ed1b From f0c06677d1105a599370ffd0c94679996c3656f2 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:27 -0800 Subject: drm/xe/pxp: Add VCS inline termination support The key termination is done with a specific submission to the VCS engine. This flow will be triggered in response to a termination interrupt, whose handling is coming in a follow-up patch in the series. v2: clean up defines and command emission code. (John) Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-4-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/instructions/xe_instr_defs.h | 1 + drivers/gpu/drm/xe/instructions/xe_mfx_commands.h | 28 ++++++ drivers/gpu/drm/xe/instructions/xe_mi_commands.h | 5 + drivers/gpu/drm/xe/xe_lrc.h | 3 +- drivers/gpu/drm/xe/xe_pxp_submit.c | 114 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp_submit.h | 4 + drivers/gpu/drm/xe/xe_ring_ops.c | 4 +- 7 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/xe/instructions/xe_mfx_commands.h (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h index fd2ce7ace510..e559969468c4 100644 --- a/drivers/gpu/drm/xe/instructions/xe_instr_defs.h +++ b/drivers/gpu/drm/xe/instructions/xe_instr_defs.h @@ -16,6 +16,7 @@ #define XE_INSTR_CMD_TYPE GENMASK(31, 29) #define XE_INSTR_MI REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x0) #define XE_INSTR_GSC REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x2) +#define XE_INSTR_VIDEOPIPE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3) #define XE_INSTR_GFXPIPE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3) #define XE_INSTR_GFX_STATE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x4) diff --git a/drivers/gpu/drm/xe/instructions/xe_mfx_commands.h b/drivers/gpu/drm/xe/instructions/xe_mfx_commands.h new file mode 100644 index 000000000000..3c0c97f78e90 --- /dev/null +++ b/drivers/gpu/drm/xe/instructions/xe_mfx_commands.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef _XE_MFX_COMMANDS_H_ +#define _XE_MFX_COMMANDS_H_ + +#include "instructions/xe_instr_defs.h" + +#define MFX_CMD_SUBTYPE REG_GENMASK(28, 27) /* A.K.A cmd pipe */ +#define MFX_CMD_OPCODE REG_GENMASK(26, 24) +#define MFX_CMD_SUB_OPCODE REG_GENMASK(23, 16) +#define MFX_FLAGS_AND_LEN REG_GENMASK(15, 0) + +#define XE_MFX_INSTR(subtype, op, sub_op) \ + (XE_INSTR_VIDEOPIPE | \ + REG_FIELD_PREP(MFX_CMD_SUBTYPE, subtype) | \ + REG_FIELD_PREP(MFX_CMD_OPCODE, op) | \ + REG_FIELD_PREP(MFX_CMD_SUB_OPCODE, sub_op)) + +#define MFX_WAIT XE_MFX_INSTR(1, 0, 0) +#define MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG REG_BIT(9) +#define MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG REG_BIT(8) + +#define CRYPTO_KEY_EXCHANGE XE_MFX_INSTR(2, 6, 9) + +#endif diff --git a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h index 10ec2920d31b..167fb0f742de 100644 --- a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h +++ b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h @@ -48,6 +48,7 @@ #define MI_LRI_LEN(x) (((x) & 0xff) + 1) #define MI_FLUSH_DW __MI_INSTR(0x26) +#define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22) #define MI_FLUSH_DW_STORE_INDEX REG_BIT(21) #define MI_INVALIDATE_TLB REG_BIT(18) #define MI_FLUSH_DW_CCS REG_BIT(16) @@ -66,4 +67,8 @@ #define MI_BATCH_BUFFER_START __MI_INSTR(0x31) +#define MI_SET_APPID __MI_INSTR(0x0e) +#define MI_SET_APPID_SESSION_ID_MASK REG_GENMASK(6, 0) +#define MI_SET_APPID_SESSION_ID(x) REG_FIELD_PREP(MI_SET_APPID_SESSION_ID_MASK, x) + #endif diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h index 4206e6a8b50a..b27e80cd842a 100644 --- a/drivers/gpu/drm/xe/xe_lrc.h +++ b/drivers/gpu/drm/xe/xe_lrc.h @@ -39,7 +39,8 @@ struct xe_lrc_snapshot { u32 ctx_job_timestamp; }; -#define LRC_PPHWSP_SCRATCH_ADDR (0x34 * 4) +#define LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR (0x34 * 4) +#define LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR (0x40 * 4) struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, u32 ring_size, u16 msix_vec); diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.c b/drivers/gpu/drm/xe/xe_pxp_submit.c index 52a6143b5ebe..326baea679a3 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.c +++ b/drivers/gpu/drm/xe/xe_pxp_submit.c @@ -5,15 +5,21 @@ #include "xe_pxp_submit.h" +#include #include #include "xe_device_types.h" +#include "xe_bb.h" #include "xe_bo.h" #include "xe_exec_queue.h" #include "xe_gsc_submit.h" #include "xe_gt.h" +#include "xe_lrc.h" #include "xe_pxp_types.h" +#include "xe_sched_job.h" #include "xe_vm.h" +#include "instructions/xe_mfx_commands.h" +#include "instructions/xe_mi_commands.h" /* * The VCS is used for kernel-owned GGTT submissions to issue key termination. @@ -197,3 +203,111 @@ void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp) destroy_gsc_client_resources(&pxp->gsc_res); destroy_vcs_execution_resources(pxp); } + +#define emit_cmd(xe_, map_, offset_, val_) \ + xe_map_wr(xe_, map_, (offset_) * sizeof(u32), u32, val_) + +/* stall until prior PXP and MFX/HCP/HUC objects are completed */ +#define MFX_WAIT_PXP (MFX_WAIT | \ + MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | \ + MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG) +static u32 pxp_emit_wait(struct xe_device *xe, struct iosys_map *batch, u32 offset) +{ + /* wait for cmds to go through */ + emit_cmd(xe, batch, offset++, MFX_WAIT_PXP); + emit_cmd(xe, batch, offset++, 0); + + return offset; +} + +static u32 pxp_emit_session_selection(struct xe_device *xe, struct iosys_map *batch, + u32 offset, u32 idx) +{ + offset = pxp_emit_wait(xe, batch, offset); + + /* pxp off */ + emit_cmd(xe, batch, offset++, MI_FLUSH_DW | MI_FLUSH_IMM_DW); + emit_cmd(xe, batch, offset++, 0); + emit_cmd(xe, batch, offset++, 0); + emit_cmd(xe, batch, offset++, 0); + + /* select session */ + emit_cmd(xe, batch, offset++, MI_SET_APPID | MI_SET_APPID_SESSION_ID(idx)); + emit_cmd(xe, batch, offset++, 0); + + offset = pxp_emit_wait(xe, batch, offset); + + /* pxp on */ + emit_cmd(xe, batch, offset++, MI_FLUSH_DW | + MI_FLUSH_DW_PROTECTED_MEM_EN | + MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX | + MI_FLUSH_IMM_DW); + emit_cmd(xe, batch, offset++, LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR | + MI_FLUSH_DW_USE_GTT); + emit_cmd(xe, batch, offset++, 0); + emit_cmd(xe, batch, offset++, 0); + + offset = pxp_emit_wait(xe, batch, offset); + + return offset; +} + +static u32 pxp_emit_inline_termination(struct xe_device *xe, + struct iosys_map *batch, u32 offset) +{ + /* session inline termination */ + emit_cmd(xe, batch, offset++, CRYPTO_KEY_EXCHANGE); + emit_cmd(xe, batch, offset++, 0); + + return offset; +} + +static u32 pxp_emit_session_termination(struct xe_device *xe, struct iosys_map *batch, + u32 offset, u32 idx) +{ + offset = pxp_emit_session_selection(xe, batch, offset, idx); + offset = pxp_emit_inline_termination(xe, batch, offset); + + return offset; +} + +/** + * xe_pxp_submit_session_termination - submits a PXP inline termination + * @pxp: the xe_pxp structure + * @id: the session to terminate + * + * Emit an inline termination via the VCS engine to terminate a session. + * + * Returns 0 if the submission is successful, an errno value otherwise. + */ +int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id) +{ + struct xe_sched_job *job; + struct dma_fence *fence; + long timeout; + u32 offset = 0; + u64 addr = xe_bo_ggtt_addr(pxp->vcs_exec.bo); + + offset = pxp_emit_session_termination(pxp->xe, &pxp->vcs_exec.bo->vmap, offset, id); + offset = pxp_emit_wait(pxp->xe, &pxp->vcs_exec.bo->vmap, offset); + emit_cmd(pxp->xe, &pxp->vcs_exec.bo->vmap, offset, MI_BATCH_BUFFER_END); + + job = xe_sched_job_create(pxp->vcs_exec.q, &addr); + if (IS_ERR(job)) + return PTR_ERR(job); + + xe_sched_job_arm(job); + fence = dma_fence_get(&job->drm.s_fence->finished); + xe_sched_job_push(job); + + timeout = dma_fence_wait_timeout(fence, false, HZ); + + dma_fence_put(fence); + + if (!timeout) + return -ETIMEDOUT; + else if (timeout < 0) + return timeout; + + return 0; +} diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.h b/drivers/gpu/drm/xe/xe_pxp_submit.h index fd21ac935be1..4ee8c0acfed9 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.h +++ b/drivers/gpu/drm/xe/xe_pxp_submit.h @@ -6,9 +6,13 @@ #ifndef __XE_PXP_SUBMIT_H__ #define __XE_PXP_SUBMIT_H__ +#include + struct xe_pxp; int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp); void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp); +int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id); + #endif /* __XE_PXP_SUBMIT_H__ */ diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c index 9f327f27c072..0c230ee53bba 100644 --- a/drivers/gpu/drm/xe/xe_ring_ops.c +++ b/drivers/gpu/drm/xe/xe_ring_ops.c @@ -118,7 +118,7 @@ static int emit_flush_invalidate(u32 flag, u32 *dw, int i) dw[i++] |= MI_INVALIDATE_TLB | MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_IMM_DW | MI_FLUSH_DW_STORE_INDEX; - dw[i++] = LRC_PPHWSP_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; + dw[i++] = LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; dw[i++] = 0; dw[i++] = ~0U; @@ -156,7 +156,7 @@ static int emit_pipe_invalidate(u32 mask_flags, bool invalidate_tlb, u32 *dw, flags &= ~mask_flags; - return emit_pipe_control(dw, i, 0, flags, LRC_PPHWSP_SCRATCH_ADDR, 0); + return emit_pipe_control(dw, i, 0, flags, LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0); } static int emit_store_imm_ppgtt_posted(u64 addr, u64 value, -- cgit v1.2.3-59-g8ed1b From 96e84a2f5a5ba0efaaefb0dd5072e4b2e7f31f0e Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:28 -0800 Subject: drm/xe/pxp: Add GSC session invalidation support After a session is terminated, we need to inform the GSC so that it can clean up its side of the allocation. This is done by sending an invalidation command with the session ID. The invalidation will be triggered in response to a termination, interrupt, whose handling is coming in the next patch in the series. v2: Better comment and error messages (John) Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-5-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h | 13 ++ drivers/gpu/drm/xe/xe_pxp_submit.c | 228 ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp_submit.h | 3 + 3 files changed, 244 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h b/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h index f3c4cf10ba20..f0da65ccdda2 100644 --- a/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h +++ b/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h @@ -31,6 +31,7 @@ enum pxp_status { PXP_STATUS_NOT_READY = 0x100e, PXP_STATUS_PLATFCONFIG_KF1_NOVERIF = 0x101a, PXP_STATUS_PLATFCONFIG_KF1_BAD = 0x101f, + PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED = 0x1037, PXP_STATUS_OP_NOT_PERMITTED = 0x4013 }; @@ -49,6 +50,7 @@ struct pxp_cmd_header { u32 buffer_len; } __packed; +#define PXP43_CMDID_INVALIDATE_STREAM_KEY 0x00000007 #define PXP43_CMDID_NEW_HUC_AUTH 0x0000003F /* MTL+ */ /* PXP-Input-Packet: HUC Auth-only */ @@ -63,4 +65,15 @@ struct pxp43_huc_auth_out { struct pxp_cmd_header header; } __packed; +/* PXP-Input-Packet: Invalidate Stream Key */ +struct pxp43_inv_stream_key_in { + struct pxp_cmd_header header; + u32 rsvd[3]; +} __packed; + +/* PXP-Output-Packet: Invalidate Stream Key */ +struct pxp43_inv_stream_key_out { + struct pxp_cmd_header header; + u32 rsvd; +} __packed; #endif diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.c b/drivers/gpu/drm/xe/xe_pxp_submit.c index 326baea679a3..f5f6b18c1054 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.c +++ b/drivers/gpu/drm/xe/xe_pxp_submit.c @@ -15,9 +15,13 @@ #include "xe_gsc_submit.h" #include "xe_gt.h" #include "xe_lrc.h" +#include "xe_map.h" #include "xe_pxp_types.h" #include "xe_sched_job.h" #include "xe_vm.h" +#include "abi/gsc_command_header_abi.h" +#include "abi/gsc_pxp_commands_abi.h" +#include "instructions/xe_gsc_commands.h" #include "instructions/xe_mfx_commands.h" #include "instructions/xe_mi_commands.h" @@ -311,3 +315,227 @@ int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id) return 0; } + +static bool +is_fw_err_platform_config(u32 type) +{ + switch (type) { + case PXP_STATUS_ERROR_API_VERSION: + case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF: + case PXP_STATUS_PLATFCONFIG_KF1_BAD: + case PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED: + return true; + default: + break; + } + return false; +} + +static const char * +fw_err_to_string(u32 type) +{ + switch (type) { + case PXP_STATUS_ERROR_API_VERSION: + return "ERR_API_VERSION"; + case PXP_STATUS_NOT_READY: + return "ERR_NOT_READY"; + case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF: + case PXP_STATUS_PLATFCONFIG_KF1_BAD: + case PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED: + return "ERR_PLATFORM_CONFIG"; + default: + break; + } + return NULL; +} + +static int pxp_pkt_submit(struct xe_exec_queue *q, u64 batch_addr) +{ + struct xe_gt *gt = q->gt; + struct xe_device *xe = gt_to_xe(gt); + struct xe_sched_job *job; + struct dma_fence *fence; + long timeout; + + xe_assert(xe, q->hwe->engine_id == XE_HW_ENGINE_GSCCS0); + + job = xe_sched_job_create(q, &batch_addr); + if (IS_ERR(job)) + return PTR_ERR(job); + + xe_sched_job_arm(job); + fence = dma_fence_get(&job->drm.s_fence->finished); + xe_sched_job_push(job); + + timeout = dma_fence_wait_timeout(fence, false, HZ); + dma_fence_put(fence); + if (timeout < 0) + return timeout; + else if (!timeout) + return -ETIME; + + return 0; +} + +static void emit_pxp_heci_cmd(struct xe_device *xe, struct iosys_map *batch, + u64 addr_in, u32 size_in, u64 addr_out, u32 size_out) +{ + u32 len = 0; + + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, GSC_HECI_CMD_PKT); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, lower_32_bits(addr_in)); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, upper_32_bits(addr_in)); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, size_in); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, lower_32_bits(addr_out)); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, upper_32_bits(addr_out)); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, size_out); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, 0); + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, MI_BATCH_BUFFER_END); +} + +#define GSC_PENDING_RETRY_MAXCOUNT 40 +#define GSC_PENDING_RETRY_PAUSE_MS 50 +static int gsccs_send_message(struct xe_pxp_gsc_client_resources *gsc_res, + void *msg_in, size_t msg_in_size, + void *msg_out, size_t msg_out_size_max) +{ + struct xe_device *xe = gsc_res->vm->xe; + const size_t max_msg_size = gsc_res->inout_size - sizeof(struct intel_gsc_mtl_header); + u32 wr_offset; + u32 rd_offset; + u32 reply_size; + u32 min_reply_size = 0; + int ret; + int retry = GSC_PENDING_RETRY_MAXCOUNT; + + if (msg_in_size > max_msg_size || msg_out_size_max > max_msg_size) + return -ENOSPC; + + wr_offset = xe_gsc_emit_header(xe, &gsc_res->msg_in, 0, + HECI_MEADDRESS_PXP, + gsc_res->host_session_handle, + msg_in_size); + + /* NOTE: zero size packets are used for session-cleanups */ + if (msg_in && msg_in_size) { + xe_map_memcpy_to(xe, &gsc_res->msg_in, wr_offset, + msg_in, msg_in_size); + min_reply_size = sizeof(struct pxp_cmd_header); + } + + /* Make sure the reply header does not contain stale data */ + xe_gsc_poison_header(xe, &gsc_res->msg_out, 0); + + /* + * The BO is mapped at address 0 of the PPGTT, so no need to add its + * base offset when calculating the in/out addresses. + */ + emit_pxp_heci_cmd(xe, &gsc_res->batch, PXP_BB_SIZE, + wr_offset + msg_in_size, PXP_BB_SIZE + gsc_res->inout_size, + wr_offset + msg_out_size_max); + + xe_device_wmb(xe); + + /* + * If the GSC needs to communicate with CSME to complete our request, + * it'll set the "pending" flag in the return header. In this scenario + * we're expected to wait 50ms to give some time to the proxy code to + * handle the GSC<->CSME communication and then try again. Note that, + * although in most case the 50ms window is enough, the proxy flow is + * not actually guaranteed to complete within that time period, so we + * might have to try multiple times, up to a worst case of 2 seconds, + * after which the request is considered aborted. + */ + do { + ret = pxp_pkt_submit(gsc_res->q, 0); + if (ret) + break; + + if (xe_gsc_check_and_update_pending(xe, &gsc_res->msg_in, 0, + &gsc_res->msg_out, 0)) { + ret = -EAGAIN; + msleep(GSC_PENDING_RETRY_PAUSE_MS); + } + } while (--retry && ret == -EAGAIN); + + if (ret) { + drm_err(&xe->drm, "failed to submit GSC PXP message (%pe)\n", ERR_PTR(ret)); + return ret; + } + + ret = xe_gsc_read_out_header(xe, &gsc_res->msg_out, 0, + min_reply_size, &rd_offset); + if (ret) { + drm_err(&xe->drm, "invalid GSC reply for PXP (%pe)\n", ERR_PTR(ret)); + return ret; + } + + if (msg_out && min_reply_size) { + reply_size = xe_map_rd_field(xe, &gsc_res->msg_out, rd_offset, + struct pxp_cmd_header, buffer_len); + reply_size += sizeof(struct pxp_cmd_header); + + if (reply_size > msg_out_size_max) { + drm_warn(&xe->drm, "PXP reply size overflow: %u (%zu)\n", + reply_size, msg_out_size_max); + reply_size = msg_out_size_max; + } + + xe_map_memcpy_from(xe, msg_out, &gsc_res->msg_out, + rd_offset, reply_size); + } + + xe_gsc_poison_header(xe, &gsc_res->msg_in, 0); + + return ret; +} + +/** + * xe_pxp_submit_session_invalidation - submits a PXP GSC invalidation + * @gsc_res: the pxp client resources + * @id: the session to invalidate + * + * Submit a message to the GSC FW to notify it that a session has been + * terminated and is therefore invalid. + * + * Returns 0 if the submission is successful, an errno value otherwise. + */ +int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, u32 id) +{ + struct xe_device *xe = gsc_res->vm->xe; + struct pxp43_inv_stream_key_in msg_in = {0}; + struct pxp43_inv_stream_key_out msg_out = {0}; + int ret = 0; + + /* + * Stream key invalidation reuses the same version 4.2 input/output + * command format but firmware requires 4.3 API interaction + */ + msg_in.header.api_version = PXP_APIVER(4, 3); + msg_in.header.command_id = PXP43_CMDID_INVALIDATE_STREAM_KEY; + msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header); + + msg_in.header.stream_id = FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_VALID, 1); + msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_APP_TYPE, 0); + msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_ID, id); + + ret = gsccs_send_message(gsc_res, &msg_in, sizeof(msg_in), + &msg_out, sizeof(msg_out)); + if (ret) { + drm_err(&xe->drm, "Failed to invalidate PXP stream-key %u (%pe)\n", + id, ERR_PTR(ret)); + } else if (msg_out.header.status != 0) { + ret = -EIO; + + if (is_fw_err_platform_config(msg_out.header.status)) + drm_info_once(&xe->drm, + "Failed to invalidate PXP stream-key %u: BIOS/SOC 0x%08x(%s)\n", + id, msg_out.header.status, + fw_err_to_string(msg_out.header.status)); + else + drm_dbg(&xe->drm, "Failed to invalidate stream-key %u, s=0x%08x\n", + id, msg_out.header.status); + } + + return ret; +} diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.h b/drivers/gpu/drm/xe/xe_pxp_submit.h index 4ee8c0acfed9..48fdc9b09116 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.h +++ b/drivers/gpu/drm/xe/xe_pxp_submit.h @@ -9,10 +9,13 @@ #include struct xe_pxp; +struct xe_pxp_gsc_client_resources; int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp); void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp); int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id); +int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, + u32 id); #endif /* __XE_PXP_SUBMIT_H__ */ -- cgit v1.2.3-59-g8ed1b From 3b506d73ec14977f3107ade94346cfb169c6f3b9 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:29 -0800 Subject: drm/xe/pxp: Handle the PXP termination interrupt When something happen to the session, the HW generates a termination interrupt. In reply to this, the driver is required to submit an inline session termination via the VCS, trigger the global termination and notify the GSC FW that the session is now invalid. v2: rename ARB define to make it cleaner to move it to uapi (John) v3: fix parameter name in documentation Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-6-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/regs/xe_irq_regs.h | 8 ++ drivers/gpu/drm/xe/regs/xe_pxp_regs.h | 6 ++ drivers/gpu/drm/xe/xe_irq.c | 20 ++++- drivers/gpu/drm/xe/xe_pxp.c | 139 +++++++++++++++++++++++++++++++++- drivers/gpu/drm/xe/xe_pxp.h | 7 ++ drivers/gpu/drm/xe/xe_pxp_types.h | 13 ++++ 6 files changed, 189 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/regs/xe_irq_regs.h b/drivers/gpu/drm/xe/regs/xe_irq_regs.h index 1776b3f78ccb..f0ecfcac4003 100644 --- a/drivers/gpu/drm/xe/regs/xe_irq_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_irq_regs.h @@ -44,6 +44,7 @@ #define ENGINE1_MASK REG_GENMASK(31, 16) #define ENGINE0_MASK REG_GENMASK(15, 0) #define GPM_WGBOXPERF_INTR_ENABLE XE_REG(0x19003c, XE_REG_OPTION_VF) +#define CRYPTO_RSVD_INTR_ENABLE XE_REG(0x190040) #define GUNIT_GSC_INTR_ENABLE XE_REG(0x190044, XE_REG_OPTION_VF) #define CCS_RSVD_INTR_ENABLE XE_REG(0x190048, XE_REG_OPTION_VF) @@ -54,6 +55,7 @@ #define INTR_ENGINE_INTR(x) REG_FIELD_GET(GENMASK(15, 0), x) #define OTHER_GUC_INSTANCE 0 #define OTHER_GSC_HECI2_INSTANCE 3 +#define OTHER_KCR_INSTANCE 4 #define OTHER_GSC_INSTANCE 6 #define IIR_REG_SELECTOR(x) XE_REG(0x190070 + ((x) * 4), XE_REG_OPTION_VF) @@ -65,6 +67,7 @@ #define HECI2_RSVD_INTR_MASK XE_REG(0x1900e4) #define GUC_SG_INTR_MASK XE_REG(0x1900e8, XE_REG_OPTION_VF) #define GPM_WGBOXPERF_INTR_MASK XE_REG(0x1900ec, XE_REG_OPTION_VF) +#define CRYPTO_RSVD_INTR_MASK XE_REG(0x1900f0) #define GUNIT_GSC_INTR_MASK XE_REG(0x1900f4, XE_REG_OPTION_VF) #define CCS0_CCS1_INTR_MASK XE_REG(0x190100) #define CCS2_CCS3_INTR_MASK XE_REG(0x190104) @@ -79,4 +82,9 @@ #define GT_CS_MASTER_ERROR_INTERRUPT REG_BIT(3) #define GT_RENDER_USER_INTERRUPT REG_BIT(0) +/* irqs for OTHER_KCR_INSTANCE */ +#define KCR_PXP_STATE_TERMINATED_INTERRUPT REG_BIT(1) +#define KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT REG_BIT(2) +#define KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT REG_BIT(3) + #endif diff --git a/drivers/gpu/drm/xe/regs/xe_pxp_regs.h b/drivers/gpu/drm/xe/regs/xe_pxp_regs.h index d67cf210d23d..aa158938b42e 100644 --- a/drivers/gpu/drm/xe/regs/xe_pxp_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_pxp_regs.h @@ -14,4 +14,10 @@ #define KCR_INIT XE_REG(0x3860f0) #define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14) +/* KCR hwdrm session in play status 0-31 */ +#define KCR_SIP XE_REG(0x386260) + +/* PXP global terminate register for session termination */ +#define KCR_GLOBAL_TERMINATE XE_REG(0x3860f8) + #endif /* __XE_PXP_REGS_H__ */ diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c index 32f5a67a917b..bf092e6391c7 100644 --- a/drivers/gpu/drm/xe/xe_irq.c +++ b/drivers/gpu/drm/xe/xe_irq.c @@ -20,6 +20,7 @@ #include "xe_hw_engine.h" #include "xe_memirq.h" #include "xe_mmio.h" +#include "xe_pxp.h" #include "xe_sriov.h" /* @@ -208,6 +209,15 @@ void xe_irq_enable_hwe(struct xe_gt *gt) } if (heci_mask) xe_mmio_write32(mmio, HECI2_RSVD_INTR_MASK, ~(heci_mask << 16)); + + if (xe_pxp_is_supported(xe)) { + u32 kcr_mask = KCR_PXP_STATE_TERMINATED_INTERRUPT | + KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT | + KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT; + + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_ENABLE, kcr_mask << 16); + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_MASK, ~(kcr_mask << 16)); + } } } @@ -330,9 +340,15 @@ static void gt_irq_handler(struct xe_tile *tile, } if (class == XE_ENGINE_CLASS_OTHER) { - /* HECI GSCFI interrupts come from outside of GT */ + /* + * HECI GSCFI interrupts come from outside of GT. + * KCR irqs come from inside GT but are handled + * by the global PXP subsystem. + */ if (xe->info.has_heci_gscfi && instance == OTHER_GSC_INSTANCE) xe_heci_gsc_irq_handler(xe, intr_vec); + else if (instance == OTHER_KCR_INSTANCE) + xe_pxp_irq_handler(xe, intr_vec); else gt_other_irq_handler(engine_gt, instance, intr_vec); } @@ -510,6 +526,8 @@ static void gt_irq_reset(struct xe_tile *tile) xe_mmio_write32(mmio, GUNIT_GSC_INTR_ENABLE, 0); xe_mmio_write32(mmio, GUNIT_GSC_INTR_MASK, ~0); xe_mmio_write32(mmio, HECI2_RSVD_INTR_MASK, ~0); + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_ENABLE, 0); + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_MASK, ~0); } xe_mmio_write32(mmio, GPM_WGBOXPERF_INTR_ENABLE, 0); diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 89d71a69cdff..1452a4763ac2 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -12,9 +12,11 @@ #include "xe_gt.h" #include "xe_gt_types.h" #include "xe_mmio.h" +#include "xe_pm.h" #include "xe_pxp_submit.h" #include "xe_pxp_types.h" #include "xe_uc_fw.h" +#include "regs/xe_irq_regs.h" #include "regs/xe_pxp_regs.h" /** @@ -25,11 +27,132 @@ * integrated parts. */ -static bool pxp_is_supported(const struct xe_device *xe) +#define ARB_SESSION DRM_XE_PXP_HWDRM_DEFAULT_SESSION /* shorter define */ + +bool xe_pxp_is_supported(const struct xe_device *xe) { return xe->info.has_pxp && IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY); } +static bool pxp_is_enabled(const struct xe_pxp *pxp) +{ + return pxp; +} + +static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play) +{ + struct xe_gt *gt = pxp->gt; + u32 mask = BIT(id); + + return xe_mmio_wait32(>->mmio, KCR_SIP, mask, in_play ? mask : 0, + 250, NULL, false); +} + +static void pxp_terminate(struct xe_pxp *pxp) +{ + int ret = 0; + struct xe_device *xe = pxp->xe; + struct xe_gt *gt = pxp->gt; + unsigned int fw_ref; + + drm_dbg(&xe->drm, "Terminating PXP\n"); + + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) { + ret = -EIO; + goto out; + } + + /* terminate the hw session */ + ret = xe_pxp_submit_session_termination(pxp, ARB_SESSION); + if (ret) + goto out; + + ret = pxp_wait_for_session_state(pxp, ARB_SESSION, false); + if (ret) + goto out; + + /* Trigger full HW cleanup */ + xe_mmio_write32(>->mmio, KCR_GLOBAL_TERMINATE, 1); + + /* now we can tell the GSC to clean up its own state */ + ret = xe_pxp_submit_session_invalidation(&pxp->gsc_res, ARB_SESSION); + +out: + xe_force_wake_put(gt_to_fw(gt), fw_ref); + + if (ret) + drm_err(&xe->drm, "PXP termination failed: %pe\n", ERR_PTR(ret)); +} + +static void pxp_terminate_complete(struct xe_pxp *pxp) +{ + /* TODO mark the session as ready to start */ +} + +static void pxp_irq_work(struct work_struct *work) +{ + struct xe_pxp *pxp = container_of(work, typeof(*pxp), irq.work); + struct xe_device *xe = pxp->xe; + u32 events = 0; + + spin_lock_irq(&xe->irq.lock); + events = pxp->irq.events; + pxp->irq.events = 0; + spin_unlock_irq(&xe->irq.lock); + + if (!events) + return; + + /* + * If we're processing a termination irq while suspending then don't + * bother, we're going to re-init everything on resume anyway. + */ + if ((events & PXP_TERMINATION_REQUEST) && !xe_pm_runtime_get_if_active(xe)) + return; + + if (events & PXP_TERMINATION_REQUEST) { + events &= ~PXP_TERMINATION_COMPLETE; + pxp_terminate(pxp); + } + + if (events & PXP_TERMINATION_COMPLETE) + pxp_terminate_complete(pxp); + + if (events & PXP_TERMINATION_REQUEST) + xe_pm_runtime_put(xe); +} + +/** + * xe_pxp_irq_handler - Handles PXP interrupts. + * @xe: the xe_device structure + * @iir: interrupt vector + */ +void xe_pxp_irq_handler(struct xe_device *xe, u16 iir) +{ + struct xe_pxp *pxp = xe->pxp; + + if (!pxp_is_enabled(pxp)) { + drm_err(&xe->drm, "PXP irq 0x%x received with PXP disabled!\n", iir); + return; + } + + lockdep_assert_held(&xe->irq.lock); + + if (unlikely(!iir)) + return; + + if (iir & (KCR_PXP_STATE_TERMINATED_INTERRUPT | + KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT)) + pxp->irq.events |= PXP_TERMINATION_REQUEST; + + if (iir & KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT) + pxp->irq.events |= PXP_TERMINATION_COMPLETE; + + if (pxp->irq.events) + queue_work(pxp->irq.wq, &pxp->irq.work); +} + static int kcr_pxp_set_status(const struct xe_pxp *pxp, bool enable) { u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) : @@ -60,6 +183,7 @@ static void pxp_fini(void *arg) { struct xe_pxp *pxp = arg; + destroy_workqueue(pxp->irq.wq); xe_pxp_destroy_execution_resources(pxp); /* no need to explicitly disable KCR since we're going to do an FLR */ @@ -83,7 +207,7 @@ int xe_pxp_init(struct xe_device *xe) struct xe_pxp *pxp; int err; - if (!pxp_is_supported(xe)) + if (!xe_pxp_is_supported(xe)) return -EOPNOTSUPP; /* we only support PXP on single tile devices with a media GT */ @@ -105,12 +229,19 @@ int xe_pxp_init(struct xe_device *xe) if (!pxp) return -ENOMEM; + INIT_WORK(&pxp->irq.work, pxp_irq_work); pxp->xe = xe; pxp->gt = gt; + pxp->irq.wq = alloc_ordered_workqueue("pxp-wq", 0); + if (!pxp->irq.wq) { + err = -ENOMEM; + goto out_free; + } + err = kcr_pxp_enable(pxp); if (err) - goto out_free; + goto out_wq; err = xe_pxp_allocate_execution_resources(pxp); if (err) @@ -122,6 +253,8 @@ int xe_pxp_init(struct xe_device *xe) out_kcr_disable: kcr_pxp_disable(pxp); +out_wq: + destroy_workqueue(pxp->irq.wq); out_free: drmm_kfree(&xe->drm, pxp); return err; diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index 00f5e688c0d9..39435c644dcd 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -6,8 +6,15 @@ #ifndef __XE_PXP_H__ #define __XE_PXP_H__ +#include + struct xe_device; +#define DRM_XE_PXP_HWDRM_DEFAULT_SESSION 0xF /* TODO: move to uapi */ + +bool xe_pxp_is_supported(const struct xe_device *xe); + int xe_pxp_init(struct xe_device *xe); +void xe_pxp_irq_handler(struct xe_device *xe, u16 iir); #endif /* __XE_PXP_H__ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h index 0f86b50756cc..311d08111b5f 100644 --- a/drivers/gpu/drm/xe/xe_pxp_types.h +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -8,6 +8,7 @@ #include #include +#include struct xe_bo; struct xe_exec_queue; @@ -69,6 +70,18 @@ struct xe_pxp { /** @gsc_res: kernel-owned objects for PXP submissions to the GSCCS */ struct xe_pxp_gsc_client_resources gsc_res; + + /** @irq: wrapper for the worker and queue used for PXP irq support */ + struct { + /** @irq.work: worker that manages irq events. */ + struct work_struct work; + /** @irq.wq: workqueue on which to queue the irq work. */ + struct workqueue_struct *wq; + /** @irq.events: pending events, protected with xe->irq.lock. */ + u32 events; +#define PXP_TERMINATION_REQUEST BIT(0) +#define PXP_TERMINATION_COMPLETE BIT(1) + } irq; }; #endif /* __XE_PXP_TYPES_H__ */ -- cgit v1.2.3-59-g8ed1b From 0387d46ea7fd0496375b8668385db16ce6172ece Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:30 -0800 Subject: drm/xe/pxp: Add GSC session initialization support A session is initialized (i.e. started) by sending a message to the GSC. The initialization will be triggered when a user opts-in to using PXP; the interface for that is coming in a follow-up patch in the series. v2: clean up error messages, use new ARB define (John) Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-7-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h | 21 ++++++++++++ drivers/gpu/drm/xe/xe_pxp_submit.c | 47 +++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp_submit.h | 1 + 3 files changed, 69 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h b/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h index f0da65ccdda2..290e431cf10d 100644 --- a/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h +++ b/drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h @@ -51,6 +51,7 @@ struct pxp_cmd_header { } __packed; #define PXP43_CMDID_INVALIDATE_STREAM_KEY 0x00000007 +#define PXP43_CMDID_INIT_SESSION 0x00000036 #define PXP43_CMDID_NEW_HUC_AUTH 0x0000003F /* MTL+ */ /* PXP-Input-Packet: HUC Auth-only */ @@ -65,6 +66,26 @@ struct pxp43_huc_auth_out { struct pxp_cmd_header header; } __packed; +/* PXP-Input-Packet: Init PXP session */ +struct pxp43_create_arb_in { + struct pxp_cmd_header header; + /* header.stream_id fields for vesion 4.3 of Init PXP session: */ + #define PXP43_INIT_SESSION_VALID BIT(0) + #define PXP43_INIT_SESSION_APPTYPE BIT(1) + #define PXP43_INIT_SESSION_APPID GENMASK(17, 2) + u32 protection_mode; + #define PXP43_INIT_SESSION_PROTECTION_ARB 0x2 + u32 sub_session_id; + u32 init_flags; + u32 rsvd[12]; +} __packed; + +/* PXP-Input-Packet: Init PXP session */ +struct pxp43_create_arb_out { + struct pxp_cmd_header header; + u32 rsvd[8]; +} __packed; + /* PXP-Input-Packet: Invalidate Stream Key */ struct pxp43_inv_stream_key_in { struct pxp_cmd_header header; diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.c b/drivers/gpu/drm/xe/xe_pxp_submit.c index f5f6b18c1054..b50fe037c74b 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.c +++ b/drivers/gpu/drm/xe/xe_pxp_submit.c @@ -16,6 +16,7 @@ #include "xe_gt.h" #include "xe_lrc.h" #include "xe_map.h" +#include "xe_pxp.h" #include "xe_pxp_types.h" #include "xe_sched_job.h" #include "xe_vm.h" @@ -490,6 +491,52 @@ static int gsccs_send_message(struct xe_pxp_gsc_client_resources *gsc_res, return ret; } +/** + * xe_pxp_submit_session_init - submits a PXP GSC session initialization + * @gsc_res: the pxp client resources + * @id: the session to initialize + * + * Submit a message to the GSC FW to initialize (i.e. start) a PXP session. + * + * Returns 0 if the submission is successful, an errno value otherwise. + */ +int xe_pxp_submit_session_init(struct xe_pxp_gsc_client_resources *gsc_res, u32 id) +{ + struct xe_device *xe = gsc_res->vm->xe; + struct pxp43_create_arb_in msg_in = {0}; + struct pxp43_create_arb_out msg_out = {0}; + int ret; + + msg_in.header.api_version = PXP_APIVER(4, 3); + msg_in.header.command_id = PXP43_CMDID_INIT_SESSION; + msg_in.header.stream_id = (FIELD_PREP(PXP43_INIT_SESSION_APPID, id) | + FIELD_PREP(PXP43_INIT_SESSION_VALID, 1) | + FIELD_PREP(PXP43_INIT_SESSION_APPTYPE, 0)); + msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header); + + if (id == DRM_XE_PXP_HWDRM_DEFAULT_SESSION) + msg_in.protection_mode = PXP43_INIT_SESSION_PROTECTION_ARB; + + ret = gsccs_send_message(gsc_res, &msg_in, sizeof(msg_in), + &msg_out, sizeof(msg_out)); + if (ret) { + drm_err(&xe->drm, "Failed to init PXP session %u (%pe)\n", id, ERR_PTR(ret)); + } else if (msg_out.header.status != 0) { + ret = -EIO; + + if (is_fw_err_platform_config(msg_out.header.status)) + drm_info_once(&xe->drm, + "Failed to init PXP session %u due to BIOS/SOC, s=0x%x(%s)\n", + id, msg_out.header.status, + fw_err_to_string(msg_out.header.status)); + else + drm_dbg(&xe->drm, "Failed to init PXP session %u, s=0x%x\n", + id, msg_out.header.status); + } + + return ret; +} + /** * xe_pxp_submit_session_invalidation - submits a PXP GSC invalidation * @gsc_res: the pxp client resources diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.h b/drivers/gpu/drm/xe/xe_pxp_submit.h index 48fdc9b09116..c9efda02f4b0 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.h +++ b/drivers/gpu/drm/xe/xe_pxp_submit.h @@ -14,6 +14,7 @@ struct xe_pxp_gsc_client_resources; int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp); void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp); +int xe_pxp_submit_session_init(struct xe_pxp_gsc_client_resources *gsc_res, u32 id); int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id); int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, u32 id); -- cgit v1.2.3-59-g8ed1b From f8caa80154c4b5481476d1aad8bef335b5f90e6d Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:31 -0800 Subject: drm/xe/pxp: Add PXP queue tracking and session start We expect every queue that uses PXP to be marked as doing so, to allow the driver to correctly manage the encryption status. The API for doing this from userspace is coming in the next patch, while this patch implement the management side of things. When a PXP queue is created, the driver will do the following: - Start the default PXP session if it is not already running; - assign an rpm ref to the queue to keep for its lifetime (this is required because PXP HWDRM sessions are killed by the HW suspend flow). Since PXP start and termination can race each other, this patch also introduces locking and a state machine to keep track of the pending operations. Note that since we'll need to take the lock from the suspend/resume paths as well, we can't do submissions while holding it, which means we need a slightly more complicated state machine to keep track of intermediate steps. v4: new patch in the series, split from the following interface patch to keep review manageable. Lock and status rework to not do submissions under lock. v5: Improve comments and error logs (John) Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-8-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_exec_queue.c | 1 + drivers/gpu/drm/xe/xe_exec_queue_types.h | 6 + drivers/gpu/drm/xe/xe_pxp.c | 383 ++++++++++++++++++++++++++++++- drivers/gpu/drm/xe/xe_pxp.h | 5 + drivers/gpu/drm/xe/xe_pxp_types.h | 30 +++ 5 files changed, 419 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 252bfa11cae9..2ec4e2eb6f2a 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -78,6 +78,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, INIT_LIST_HEAD(&q->lr.link); INIT_LIST_HEAD(&q->multi_gt_link); INIT_LIST_HEAD(&q->hw_engine_group_link); + INIT_LIST_HEAD(&q->pxp.link); q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us; q->sched_props.preempt_timeout_us = diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h index 5af5419cec7a..6d85a069947f 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h @@ -130,6 +130,12 @@ struct xe_exec_queue { struct list_head link; } lr; + /** @pxp: PXP info tracking */ + struct { + /** @pxp.link: link into the list of PXP exec queues */ + struct list_head link; + } pxp; + /** @ops: submission backend exec queue operations */ const struct xe_exec_queue_ops *ops; diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 1452a4763ac2..69d49e34e34d 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -8,9 +8,13 @@ #include #include "xe_device_types.h" +#include "xe_exec_queue.h" #include "xe_force_wake.h" +#include "xe_guc_submit.h" +#include "xe_gsc_proxy.h" #include "xe_gt.h" #include "xe_gt_types.h" +#include "xe_huc.h" #include "xe_mmio.h" #include "xe_pm.h" #include "xe_pxp_submit.h" @@ -29,6 +33,15 @@ #define ARB_SESSION DRM_XE_PXP_HWDRM_DEFAULT_SESSION /* shorter define */ +/* + * A submission to GSC can take up to 250ms to complete, so use a 300ms + * timeout for activation where only one of those is involved. Termination + * additionally requires a submission to VCS and an interaction with KCR, so + * bump the timeout to 500ms for that. + */ +#define PXP_ACTIVATION_TIMEOUT_MS 300 +#define PXP_TERMINATION_TIMEOUT_MS 500 + bool xe_pxp_is_supported(const struct xe_device *xe) { return xe->info.has_pxp && IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY); @@ -39,6 +52,40 @@ static bool pxp_is_enabled(const struct xe_pxp *pxp) return pxp; } +static bool pxp_prerequisites_done(const struct xe_pxp *pxp) +{ + struct xe_gt *gt = pxp->gt; + unsigned int fw_ref; + bool ready; + + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); + + /* + * If force_wake fails we could falsely report the prerequisites as not + * done even if they are; the consequence of this would be that the + * callers won't go ahead with using PXP, but if force_wake doesn't work + * the GT is very likely in a bad state so not really a problem to abort + * PXP. Therefore, we can just log the force_wake error and not escalate + * it. + */ + XE_WARN_ON(!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)); + + /* PXP requires both HuC authentication via GSC and GSC proxy initialized */ + ready = xe_huc_is_authenticated(>->uc.huc, XE_HUC_AUTH_VIA_GSC) && + xe_gsc_proxy_init_done(>->uc.gsc); + + xe_force_wake_put(gt_to_fw(gt), fw_ref); + + return ready; +} + +static bool pxp_session_is_in_play(struct xe_pxp *pxp, u32 id) +{ + struct xe_gt *gt = pxp->gt; + + return xe_mmio_read32(>->mmio, KCR_SIP) & BIT(id); +} + static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play) { struct xe_gt *gt = pxp->gt; @@ -48,14 +95,15 @@ static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play) 250, NULL, false); } -static void pxp_terminate(struct xe_pxp *pxp) +static void pxp_invalidate_queues(struct xe_pxp *pxp); + +static int pxp_terminate_hw(struct xe_pxp *pxp) { - int ret = 0; - struct xe_device *xe = pxp->xe; struct xe_gt *gt = pxp->gt; unsigned int fw_ref; + int ret = 0; - drm_dbg(&xe->drm, "Terminating PXP\n"); + drm_dbg(&pxp->xe->drm, "Terminating PXP\n"); fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) { @@ -80,14 +128,83 @@ static void pxp_terminate(struct xe_pxp *pxp) out: xe_force_wake_put(gt_to_fw(gt), fw_ref); + return ret; +} - if (ret) +static void mark_termination_in_progress(struct xe_pxp *pxp) +{ + lockdep_assert_held(&pxp->mutex); + + reinit_completion(&pxp->termination); + pxp->status = XE_PXP_TERMINATION_IN_PROGRESS; +} + +static void pxp_terminate(struct xe_pxp *pxp) +{ + int ret = 0; + struct xe_device *xe = pxp->xe; + + if (!wait_for_completion_timeout(&pxp->activation, + msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) + drm_err(&xe->drm, "failed to wait for PXP start before termination\n"); + + mutex_lock(&pxp->mutex); + + pxp_invalidate_queues(pxp); + + /* + * If we have a termination already in progress, we need to wait for + * it to complete before queueing another one. Once the first + * termination is completed we'll set the state back to + * NEEDS_TERMINATION and leave it to the pxp start code to issue it. + */ + if (pxp->status == XE_PXP_TERMINATION_IN_PROGRESS) { + pxp->status = XE_PXP_NEEDS_ADDITIONAL_TERMINATION; + mutex_unlock(&pxp->mutex); + return; + } + + mark_termination_in_progress(pxp); + + mutex_unlock(&pxp->mutex); + + ret = pxp_terminate_hw(pxp); + if (ret) { drm_err(&xe->drm, "PXP termination failed: %pe\n", ERR_PTR(ret)); + mutex_lock(&pxp->mutex); + pxp->status = XE_PXP_ERROR; + complete_all(&pxp->termination); + mutex_unlock(&pxp->mutex); + } } static void pxp_terminate_complete(struct xe_pxp *pxp) { - /* TODO mark the session as ready to start */ + /* + * We expect PXP to be in one of 2 states when we get here: + * - XE_PXP_TERMINATION_IN_PROGRESS: a single termination event was + * requested and it is now completing, so we're ready to start. + * - XE_PXP_NEEDS_ADDITIONAL_TERMINATION: a second termination was + * requested while the first one was still being processed. + */ + mutex_lock(&pxp->mutex); + + switch (pxp->status) { + case XE_PXP_TERMINATION_IN_PROGRESS: + pxp->status = XE_PXP_READY_TO_START; + break; + case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: + pxp->status = XE_PXP_NEEDS_TERMINATION; + break; + default: + drm_err(&pxp->xe->drm, + "PXP termination complete while status was %u\n", + pxp->status); + } + + complete_all(&pxp->termination); + + mutex_unlock(&pxp->mutex); } static void pxp_irq_work(struct work_struct *work) @@ -229,10 +346,24 @@ int xe_pxp_init(struct xe_device *xe) if (!pxp) return -ENOMEM; + INIT_LIST_HEAD(&pxp->queues.list); + spin_lock_init(&pxp->queues.lock); INIT_WORK(&pxp->irq.work, pxp_irq_work); pxp->xe = xe; pxp->gt = gt; + /* + * we'll use the completions to check if there is an action pending, + * so we start them as completed and we reinit it when an action is + * triggered. + */ + init_completion(&pxp->activation); + init_completion(&pxp->termination); + complete_all(&pxp->termination); + complete_all(&pxp->activation); + + mutex_init(&pxp->mutex); + pxp->irq.wq = alloc_ordered_workqueue("pxp-wq", 0); if (!pxp->irq.wq) { err = -ENOMEM; @@ -259,3 +390,243 @@ out_free: drmm_kfree(&xe->drm, pxp); return err; } + +static int __pxp_start_arb_session(struct xe_pxp *pxp) +{ + int ret; + unsigned int fw_ref; + + fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) + return -EIO; + + if (pxp_session_is_in_play(pxp, ARB_SESSION)) { + ret = -EEXIST; + goto out_force_wake; + } + + ret = xe_pxp_submit_session_init(&pxp->gsc_res, ARB_SESSION); + if (ret) { + drm_err(&pxp->xe->drm, "Failed to init PXP arb session: %pe\n", ERR_PTR(ret)); + goto out_force_wake; + } + + ret = pxp_wait_for_session_state(pxp, ARB_SESSION, true); + if (ret) { + drm_err(&pxp->xe->drm, "PXP ARB session failed to go in play%pe\n", ERR_PTR(ret)); + goto out_force_wake; + } + + drm_dbg(&pxp->xe->drm, "PXP ARB session is active\n"); + +out_force_wake: + xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref); + return ret; +} + +static void __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) +{ + spin_lock_irq(&pxp->queues.lock); + list_add_tail(&q->pxp.link, &pxp->queues.list); + spin_unlock_irq(&pxp->queues.lock); +} + +/** + * xe_pxp_exec_queue_add - add a queue to the PXP list + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * @q: the queue to add to the list + * + * If PXP is enabled and the prerequisites are done, start the PXP ARB + * session (if not already running) and add the queue to the PXP list. Note + * that the queue must have previously been marked as using PXP with + * xe_pxp_exec_queue_set_type. + * + * Returns 0 if the PXP ARB session is running and the queue is in the list, + * -ENODEV if PXP is disabled, -EBUSY if the PXP prerequisites are not done, + * other errno value if something goes wrong during the session start. + */ +int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) +{ + int ret = 0; + + if (!pxp_is_enabled(pxp)) + return -ENODEV; + + /* + * Runtime suspend kills PXP, so we take a reference to prevent it from + * happening while we have active queues that use PXP + */ + xe_pm_runtime_get(pxp->xe); + + if (!pxp_prerequisites_done(pxp)) { + ret = -EBUSY; + goto out; + } + +wait_for_idle: + /* + * if there is an action in progress, wait for it. We need to wait + * outside the lock because the completion is done from within the lock. + * Note that the two action should never be pending at the same time. + */ + if (!wait_for_completion_timeout(&pxp->termination, + msecs_to_jiffies(PXP_TERMINATION_TIMEOUT_MS))) { + ret = -ETIMEDOUT; + goto out; + } + + if (!wait_for_completion_timeout(&pxp->activation, + msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) { + ret = -ETIMEDOUT; + goto out; + } + + mutex_lock(&pxp->mutex); + + /* If PXP is not already active, turn it on */ + switch (pxp->status) { + case XE_PXP_ERROR: + ret = -EIO; + break; + case XE_PXP_ACTIVE: + __exec_queue_add(pxp, q); + mutex_unlock(&pxp->mutex); + goto out; + case XE_PXP_READY_TO_START: + pxp->status = XE_PXP_START_IN_PROGRESS; + reinit_completion(&pxp->activation); + break; + case XE_PXP_START_IN_PROGRESS: + /* If a start is in progress then the completion must not be done */ + XE_WARN_ON(completion_done(&pxp->activation)); + mutex_unlock(&pxp->mutex); + goto wait_for_idle; + case XE_PXP_NEEDS_TERMINATION: + mark_termination_in_progress(pxp); + break; + case XE_PXP_TERMINATION_IN_PROGRESS: + case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: + /* If a termination is in progress then the completion must not be done */ + XE_WARN_ON(completion_done(&pxp->termination)); + mutex_unlock(&pxp->mutex); + goto wait_for_idle; + default: + drm_err(&pxp->xe->drm, "unexpected state during PXP start: %u\n", pxp->status); + ret = -EIO; + break; + } + + mutex_unlock(&pxp->mutex); + + if (ret) + goto out; + + if (!completion_done(&pxp->termination)) { + ret = pxp_terminate_hw(pxp); + if (ret) { + drm_err(&pxp->xe->drm, "PXP termination failed before start\n"); + mutex_lock(&pxp->mutex); + pxp->status = XE_PXP_ERROR; + mutex_unlock(&pxp->mutex); + + goto out; + } + + goto wait_for_idle; + } + + /* All the cases except for start should have exited earlier */ + XE_WARN_ON(completion_done(&pxp->activation)); + ret = __pxp_start_arb_session(pxp); + + mutex_lock(&pxp->mutex); + + complete_all(&pxp->activation); + + /* + * Any other process should wait until the state goes away from + * XE_PXP_START_IN_PROGRESS, so if the state is not that something went + * wrong. Mark the status as needing termination and try again. + */ + if (pxp->status != XE_PXP_START_IN_PROGRESS) { + drm_err(&pxp->xe->drm, "unexpected state after PXP start: %u\n", pxp->status); + pxp->status = XE_PXP_NEEDS_TERMINATION; + mutex_unlock(&pxp->mutex); + goto wait_for_idle; + } + + /* If everything went ok, update the status and add the queue to the list */ + if (!ret) { + pxp->status = XE_PXP_ACTIVE; + __exec_queue_add(pxp, q); + } else { + pxp->status = XE_PXP_ERROR; + } + + mutex_unlock(&pxp->mutex); + +out: + /* + * in the successful case the PM ref is released from + * xe_pxp_exec_queue_remove + */ + if (ret) + xe_pm_runtime_put(pxp->xe); + + return ret; +} + +/** + * xe_pxp_exec_queue_remove - remove a queue from the PXP list + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * @q: the queue to remove from the list + * + * If PXP is enabled and the exec_queue is in the list, the queue will be + * removed from the list and its PM reference will be released. It is safe to + * call this function multiple times for the same queue. + */ +void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q) +{ + bool need_pm_put = false; + + if (!pxp_is_enabled(pxp)) + return; + + spin_lock_irq(&pxp->queues.lock); + + if (!list_empty(&q->pxp.link)) { + list_del_init(&q->pxp.link); + need_pm_put = true; + } + + spin_unlock_irq(&pxp->queues.lock); + + if (need_pm_put) + xe_pm_runtime_put(pxp->xe); +} + +static void pxp_invalidate_queues(struct xe_pxp *pxp) +{ + struct xe_exec_queue *tmp, *q; + + spin_lock_irq(&pxp->queues.lock); + + /* + * Removing a queue from the PXP list requires a put of the RPM ref that + * the queue holds to keep the PXP session alive, which can't be done + * under spinlock. Since it is safe to kill a queue multiple times, we + * can leave the invalid queue in the list for now and postpone the + * removal and associated RPM put to when the queue is destroyed. + */ + list_for_each_entry(tmp, &pxp->queues.list, pxp.link) { + q = xe_exec_queue_get_unless_zero(tmp); + + if (!q) + continue; + + xe_exec_queue_kill(q); + xe_exec_queue_put(q); + } + + spin_unlock_irq(&pxp->queues.lock); +} diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index 39435c644dcd..f482567c27b5 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -9,6 +9,8 @@ #include struct xe_device; +struct xe_exec_queue; +struct xe_pxp; #define DRM_XE_PXP_HWDRM_DEFAULT_SESSION 0xF /* TODO: move to uapi */ @@ -17,4 +19,7 @@ bool xe_pxp_is_supported(const struct xe_device *xe); int xe_pxp_init(struct xe_device *xe); void xe_pxp_irq_handler(struct xe_device *xe, u16 iir); +int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q); +void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q); + #endif /* __XE_PXP_H__ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h index 311d08111b5f..bd741720f67d 100644 --- a/drivers/gpu/drm/xe/xe_pxp_types.h +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -6,7 +6,10 @@ #ifndef __XE_PXP_TYPES_H__ #define __XE_PXP_TYPES_H__ +#include #include +#include +#include #include #include @@ -16,6 +19,16 @@ struct xe_device; struct xe_gt; struct xe_vm; +enum xe_pxp_status { + XE_PXP_ERROR = -1, + XE_PXP_NEEDS_TERMINATION = 0, /* starting status */ + XE_PXP_NEEDS_ADDITIONAL_TERMINATION, + XE_PXP_TERMINATION_IN_PROGRESS, + XE_PXP_READY_TO_START, + XE_PXP_START_IN_PROGRESS, + XE_PXP_ACTIVE, +}; + /** * struct xe_pxp_gsc_client_resources - resources for GSC submission by a PXP * client. The GSC FW supports multiple GSC client active at the same time. @@ -82,6 +95,23 @@ struct xe_pxp { #define PXP_TERMINATION_REQUEST BIT(0) #define PXP_TERMINATION_COMPLETE BIT(1) } irq; + + /** @mutex: protects the pxp status and the queue list */ + struct mutex mutex; + /** @status: the current pxp status */ + enum xe_pxp_status status; + /** @activation: completion struct that tracks pxp start */ + struct completion activation; + /** @termination: completion struct that tracks terminations */ + struct completion termination; + + /** @queues: management of exec_queues that use PXP */ + struct { + /** @queues.lock: spinlock protecting the queue management */ + spinlock_t lock; + /** @queues.list: list of exec_queues that use PXP */ + struct list_head list; + } queues; }; #endif /* __XE_PXP_TYPES_H__ */ -- cgit v1.2.3-59-g8ed1b From 72d479601d67026c4fafaad21762a777cf41f906 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:32 -0800 Subject: drm/xe/pxp/uapi: Add userspace and LRC support for PXP-using queues Userspace is required to mark a queue as using PXP to guarantee that the PXP instructions will work. In addition to managing the PXP sessions, when a PXP queue is created the driver will set the relevant bits in its context control register. On submission of a valid PXP queue, the driver will validate all encrypted objects mapped to the VM to ensured they were encrypted with the current key. v2: Remove pxp_types include outside of PXP code (Jani), better comments and code cleanup (John) v3: split the internal PXP management to a separate patch for ease of review. re-order ioctl checks to always return -EINVAL if parameters are invalid, rebase on msix changes. Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-9-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/regs/xe_engine_regs.h | 1 + drivers/gpu/drm/xe/xe_exec_queue.c | 56 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_exec_queue.h | 5 +++ drivers/gpu/drm/xe/xe_exec_queue_types.h | 2 ++ drivers/gpu/drm/xe/xe_execlist.c | 2 +- drivers/gpu/drm/xe/xe_lrc.c | 18 ++++++++-- drivers/gpu/drm/xe/xe_lrc.h | 4 ++- drivers/gpu/drm/xe/xe_pxp.c | 35 +++++++++++++++++--- drivers/gpu/drm/xe/xe_pxp.h | 4 +-- include/uapi/drm/xe_drm.h | 40 ++++++++++++++++++++++- 10 files changed, 153 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index d86219dedde2..c8fd3d5ca502 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h @@ -132,6 +132,7 @@ #define RING_EXECLIST_STATUS_HI(base) XE_REG((base) + 0x234 + 4) #define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED) +#define CTX_CTRL_PXP_ENABLE REG_BIT(10) #define CTX_CTRL_OAC_CONTEXT_ENABLE REG_BIT(8) #define CTX_CTRL_RUN_ALONE REG_BIT(7) #define CTX_CTRL_INDIRECT_RING_STATE_ENABLE REG_BIT(4) diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 2ec4e2eb6f2a..6051db78d706 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -25,6 +25,7 @@ #include "xe_ring_ops_types.h" #include "xe_trace.h" #include "xe_vm.h" +#include "xe_pxp.h" enum xe_exec_queue_sched_prop { XE_EXEC_QUEUE_JOB_TIMEOUT = 0, @@ -38,6 +39,8 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue static void __xe_exec_queue_free(struct xe_exec_queue *q) { + if (xe_exec_queue_uses_pxp(q)) + xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q); if (q->vm) xe_vm_put(q->vm); @@ -113,6 +116,21 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) { struct xe_vm *vm = q->vm; int i, err; + u32 flags = 0; + + /* + * PXP workloads executing on RCS or CCS must run in isolation (i.e. no + * other workload can use the EUs at the same time). On MTL this is done + * by setting the RUNALONE bit in the LRC, while starting on Xe2 there + * is a dedicated bit for it. + */ + if (xe_exec_queue_uses_pxp(q) && + (q->class == XE_ENGINE_CLASS_RENDER || q->class == XE_ENGINE_CLASS_COMPUTE)) { + if (GRAPHICS_VER(gt_to_xe(q->gt)) >= 20) + flags |= XE_LRC_CREATE_PXP; + else + flags |= XE_LRC_CREATE_RUNALONE; + } if (vm) { err = xe_vm_lock(vm, true); @@ -121,7 +139,7 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) } for (i = 0; i < q->width; ++i) { - q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec); + q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec, flags); if (IS_ERR(q->lrc[i])) { err = PTR_ERR(q->lrc[i]); goto err_unlock; @@ -166,6 +184,19 @@ struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *v if (err) goto err_post_alloc; + /* + * We can only add the queue to the PXP list after the init is complete, + * because the PXP termination can call exec_queue_kill and that will + * go bad if the queue is only half-initialized. This means that we + * can't do it when we handle the PXP extension in __xe_exec_queue_alloc + * and we need to do it here instead. + */ + if (xe_exec_queue_uses_pxp(q)) { + err = xe_pxp_exec_queue_add(xe->pxp, q); + if (err) + goto err_post_alloc; + } + return q; err_post_alloc: @@ -254,6 +285,9 @@ void xe_exec_queue_destroy(struct kref *ref) struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount); struct xe_exec_queue *eq, *next; + if (xe_exec_queue_uses_pxp(q)) + xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q); + xe_exec_queue_last_fence_put_unlocked(q); if (!(q->flags & EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD)) { list_for_each_entry_safe(eq, next, &q->multi_gt_list, @@ -409,6 +443,22 @@ static int exec_queue_set_timeslice(struct xe_device *xe, struct xe_exec_queue * return 0; } +static int +exec_queue_set_pxp_type(struct xe_device *xe, struct xe_exec_queue *q, u64 value) +{ + if (value == DRM_XE_PXP_TYPE_NONE) + return 0; + + /* we only support HWDRM sessions right now */ + if (XE_IOCTL_DBG(xe, value != DRM_XE_PXP_TYPE_HWDRM)) + return -EINVAL; + + if (!xe_pxp_is_enabled(xe->pxp)) + return -ENODEV; + + return xe_pxp_exec_queue_set_type(xe->pxp, q, DRM_XE_PXP_TYPE_HWDRM); +} + typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe, struct xe_exec_queue *q, u64 value); @@ -416,6 +466,7 @@ typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe, static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = { [DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY] = exec_queue_set_priority, [DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice, + [DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type, }; static int exec_queue_user_ext_set_property(struct xe_device *xe, @@ -435,7 +486,8 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe, ARRAY_SIZE(exec_queue_set_property_funcs)) || XE_IOCTL_DBG(xe, ext.pad) || XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY && - ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE)) + ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE && + ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE)) return -EINVAL; idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs)); diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h index 90c7f73eab88..17bc50a7f05a 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.h +++ b/drivers/gpu/drm/xe/xe_exec_queue.h @@ -57,6 +57,11 @@ static inline bool xe_exec_queue_is_parallel(struct xe_exec_queue *q) return q->width > 1; } +static inline bool xe_exec_queue_uses_pxp(struct xe_exec_queue *q) +{ + return q->pxp.type; +} + bool xe_exec_queue_is_lr(struct xe_exec_queue *q); bool xe_exec_queue_ring_full(struct xe_exec_queue *q); diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h index 6d85a069947f..6eb7ff091534 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h @@ -132,6 +132,8 @@ struct xe_exec_queue { /** @pxp: PXP info tracking */ struct { + /** @pxp.type: PXP session type used by this queue */ + u8 type; /** @pxp.link: link into the list of PXP exec queues */ struct list_head link; } pxp; diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 5ef96deaa881..779a52daf3d7 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -269,7 +269,7 @@ struct xe_execlist_port *xe_execlist_port_create(struct xe_device *xe, port->hwe = hwe; - port->lrc = xe_lrc_create(hwe, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX); + port->lrc = xe_lrc_create(hwe, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX, 0); if (IS_ERR(port->lrc)) { err = PTR_ERR(port->lrc); goto err; diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index bbb9ffbf6367..df3ceddede07 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -883,7 +883,8 @@ static void xe_lrc_finish(struct xe_lrc *lrc) #define PVC_CTX_ACC_CTR_THOLD (0x2a + 1) static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, - struct xe_vm *vm, u32 ring_size, u16 msix_vec) + struct xe_vm *vm, u32 ring_size, u16 msix_vec, + u32 init_flags) { struct xe_gt *gt = hwe->gt; struct xe_tile *tile = gt_to_tile(gt); @@ -979,6 +980,16 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, RING_CTL_SIZE(lrc->ring.size) | RING_VALID); } + if (init_flags & XE_LRC_CREATE_RUNALONE) + xe_lrc_write_ctx_reg(lrc, CTX_CONTEXT_CONTROL, + xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | + _MASKED_BIT_ENABLE(CTX_CTRL_RUN_ALONE)); + + if (init_flags & XE_LRC_CREATE_PXP) + xe_lrc_write_ctx_reg(lrc, CTX_CONTEXT_CONTROL, + xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | + _MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE)); + xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP, 0); if (xe->info.has_asid && vm) @@ -1021,6 +1032,7 @@ err_lrc_finish: * @vm: The VM (address space) * @ring_size: LRC ring size * @msix_vec: MSI-X interrupt vector (for platforms that support it) + * @flags: LRC initialization flags * * Allocate and initialize the Logical Ring Context (LRC). * @@ -1028,7 +1040,7 @@ err_lrc_finish: * upon failure. */ struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, - u32 ring_size, u16 msix_vec) + u32 ring_size, u16 msix_vec, u32 flags) { struct xe_lrc *lrc; int err; @@ -1037,7 +1049,7 @@ struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, if (!lrc) return ERR_PTR(-ENOMEM); - err = xe_lrc_init(lrc, hwe, vm, ring_size, msix_vec); + err = xe_lrc_init(lrc, hwe, vm, ring_size, msix_vec, flags); if (err) { kfree(lrc); return ERR_PTR(err); diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h index b27e80cd842a..0b40f349ab95 100644 --- a/drivers/gpu/drm/xe/xe_lrc.h +++ b/drivers/gpu/drm/xe/xe_lrc.h @@ -42,8 +42,10 @@ struct xe_lrc_snapshot { #define LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR (0x34 * 4) #define LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR (0x40 * 4) +#define XE_LRC_CREATE_RUNALONE 0x1 +#define XE_LRC_CREATE_PXP 0x2 struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, - u32 ring_size, u16 msix_vec); + u32 ring_size, u16 msix_vec, u32 flags); void xe_lrc_destroy(struct kref *ref); /** diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 69d49e34e34d..b32121273e0d 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -6,6 +6,7 @@ #include "xe_pxp.h" #include +#include #include "xe_device_types.h" #include "xe_exec_queue.h" @@ -47,7 +48,7 @@ bool xe_pxp_is_supported(const struct xe_device *xe) return xe->info.has_pxp && IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY); } -static bool pxp_is_enabled(const struct xe_pxp *pxp) +bool xe_pxp_is_enabled(const struct xe_pxp *pxp) { return pxp; } @@ -249,7 +250,7 @@ void xe_pxp_irq_handler(struct xe_device *xe, u16 iir) { struct xe_pxp *pxp = xe->pxp; - if (!pxp_is_enabled(pxp)) { + if (!xe_pxp_is_enabled(pxp)) { drm_err(&xe->drm, "PXP irq 0x%x received with PXP disabled!\n", iir); return; } @@ -424,6 +425,27 @@ out_force_wake: return ret; } +/** + * xe_pxp_exec_queue_set_type - Mark a queue as using PXP + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * @q: the queue to mark as using PXP + * @type: the type of PXP session this queue will use + * + * Returns 0 if the selected PXP type is supported, -ENODEV otherwise. + */ +int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 type) +{ + if (!xe_pxp_is_enabled(pxp)) + return -ENODEV; + + /* we only support HWDRM sessions right now */ + xe_assert(pxp->xe, type == DRM_XE_PXP_TYPE_HWDRM); + + q->pxp.type = type; + + return 0; +} + static void __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) { spin_lock_irq(&pxp->queues.lock); @@ -449,9 +471,12 @@ int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) { int ret = 0; - if (!pxp_is_enabled(pxp)) + if (!xe_pxp_is_enabled(pxp)) return -ENODEV; + /* we only support HWDRM sessions right now */ + xe_assert(pxp->xe, q->pxp.type == DRM_XE_PXP_TYPE_HWDRM); + /* * Runtime suspend kills PXP, so we take a reference to prevent it from * happening while we have active queues that use PXP @@ -589,7 +614,7 @@ void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q) { bool need_pm_put = false; - if (!pxp_is_enabled(pxp)) + if (!xe_pxp_is_enabled(pxp)) return; spin_lock_irq(&pxp->queues.lock); @@ -599,6 +624,8 @@ void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q) need_pm_put = true; } + q->pxp.type = DRM_XE_PXP_TYPE_NONE; + spin_unlock_irq(&pxp->queues.lock); if (need_pm_put) diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index f482567c27b5..2e0ab186072a 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -12,13 +12,13 @@ struct xe_device; struct xe_exec_queue; struct xe_pxp; -#define DRM_XE_PXP_HWDRM_DEFAULT_SESSION 0xF /* TODO: move to uapi */ - bool xe_pxp_is_supported(const struct xe_device *xe); +bool xe_pxp_is_enabled(const struct xe_pxp *pxp); int xe_pxp_init(struct xe_device *xe); void xe_pxp_irq_handler(struct xe_device *xe, u16 iir); +int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 type); int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q); void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q); diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index e2160330ad01..9d53834c4c0a 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -1114,6 +1114,24 @@ struct drm_xe_vm_bind { /** * struct drm_xe_exec_queue_create - Input of &DRM_IOCTL_XE_EXEC_QUEUE_CREATE * + * This ioctl supports setting the following properties via the + * %DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY extension, which uses the + * generic @drm_xe_ext_set_property struct: + * + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY - set the queue priority. + * CAP_SYS_NICE is required to set a value above normal. + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE - set the queue timeslice + * duration in microseconds. + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE - set the type of PXP session + * this queue will be used with. Valid values are listed in enum + * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so + * there is no need to explicitly set that. When a queue of type + * %DRM_XE_PXP_TYPE_HWDRM is created, the PXP default HWDRM session + * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if isn't already running. + * Given that going into a power-saving state kills PXP HWDRM sessions, + * runtime PM will be blocked while queues of this type are alive. + * All PXP queues will be killed if a PXP invalidation event occurs. + * * The example below shows how to use @drm_xe_exec_queue_create to create * a simple exec_queue (no parallel submission) of class * &DRM_XE_ENGINE_CLASS_RENDER. @@ -1137,7 +1155,7 @@ struct drm_xe_exec_queue_create { #define DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY 0 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY 0 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE 1 - +#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE 2 /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; @@ -1756,6 +1774,26 @@ struct drm_xe_oa_stream_info { __u64 reserved[3]; }; +/** + * enum drm_xe_pxp_session_type - Supported PXP session types. + * + * We currently only support HWDRM sessions, which are used for protected + * content that ends up being displayed, but the HW supports multiple types, so + * we might extend support in the future. + */ +enum drm_xe_pxp_session_type { + /** @DRM_XE_PXP_TYPE_NONE: PXP not used */ + DRM_XE_PXP_TYPE_NONE = 0, + /** + * @DRM_XE_PXP_TYPE_HWDRM: HWDRM sessions are used for content that ends + * up on the display. + */ + DRM_XE_PXP_TYPE_HWDRM = 1, +}; + +/* ID of the protected content session managed by Xe when PXP is active */ +#define DRM_XE_PXP_HWDRM_DEFAULT_SESSION 0xf + #if defined(__cplusplus) } #endif -- cgit v1.2.3-59-g8ed1b From bd98ac2e05855ea781c9b7ad30b5e1a234aefe95 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:33 -0800 Subject: drm/xe/pxp/uapi: Add a query for PXP status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PXP prerequisites (SW proxy and HuC auth via GSC) are completed asynchronously from driver load, which means that userspace can start submitting before we're ready to start a PXP session. Therefore, we need a query that userspace can use to check not only if PXP is supported but also to wait until the prerequisites are done. v2: Improve doc, do not report TYPE_NONE as supported (José) v3: Better comments, remove unneeded copy_from_user (John) Signed-off-by: Daniele Ceraolo Spurio Cc: José Roberto de Souza Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-10-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pxp.c | 32 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp.h | 1 + drivers/gpu/drm/xe/xe_query.c | 29 +++++++++++++++++++++++++++++ include/uapi/drm/xe_drm.h | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index b32121273e0d..24aef5c0f04a 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -80,6 +80,38 @@ static bool pxp_prerequisites_done(const struct xe_pxp *pxp) return ready; } +/** + * xe_pxp_get_readiness_status - check whether PXP is ready for userspace use + * @pxp: the xe_pxp pointer (can be NULL if PXP is disabled) + * + * Returns: 0 if PXP is not ready yet, 1 if it is ready, a negative errno value + * if PXP is not supported/enabled or if something went wrong in the + * initialization of the prerequisites. Note that the return values of this + * function follow the uapi (see drm_xe_query_pxp_status), so they can be used + * directly in the query ioctl. + */ +int xe_pxp_get_readiness_status(struct xe_pxp *pxp) +{ + int ret = 0; + + if (!xe_pxp_is_enabled(pxp)) + return -ENODEV; + + /* if the GSC or HuC FW are in an error state, PXP will never work */ + if (xe_uc_fw_status_to_error(pxp->gt->uc.huc.fw.status) || + xe_uc_fw_status_to_error(pxp->gt->uc.gsc.fw.status)) + return -EIO; + + xe_pm_runtime_get(pxp->xe); + + /* PXP requires both HuC loaded and GSC proxy initialized */ + if (pxp_prerequisites_done(pxp)) + ret = 1; + + xe_pm_runtime_put(pxp->xe); + return ret; +} + static bool pxp_session_is_in_play(struct xe_pxp *pxp, u32 id) { struct xe_gt *gt = pxp->gt; diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index 2e0ab186072a..868813cc84b9 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -14,6 +14,7 @@ struct xe_pxp; bool xe_pxp_is_supported(const struct xe_device *xe); bool xe_pxp_is_enabled(const struct xe_pxp *pxp); +int xe_pxp_get_readiness_status(struct xe_pxp *pxp); int xe_pxp_init(struct xe_device *xe); void xe_pxp_irq_handler(struct xe_device *xe, u16 iir); diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c index c059639613f7..042f87a688e7 100644 --- a/drivers/gpu/drm/xe/xe_query.c +++ b/drivers/gpu/drm/xe/xe_query.c @@ -24,6 +24,7 @@ #include "xe_macros.h" #include "xe_mmio.h" #include "xe_oa.h" +#include "xe_pxp.h" #include "xe_ttm_vram_mgr.h" #include "xe_wa.h" @@ -698,6 +699,33 @@ static int query_oa_units(struct xe_device *xe, return ret ? -EFAULT : 0; } +static int query_pxp_status(struct xe_device *xe, struct drm_xe_device_query *query) +{ + struct drm_xe_query_pxp_status __user *query_ptr = u64_to_user_ptr(query->data); + size_t size = sizeof(struct drm_xe_query_pxp_status); + struct drm_xe_query_pxp_status resp = { 0 }; + int ret; + + if (query->size == 0) { + query->size = size; + return 0; + } else if (XE_IOCTL_DBG(xe, query->size != size)) { + return -EINVAL; + } + + ret = xe_pxp_get_readiness_status(xe->pxp); + if (ret < 0) + return ret; + + resp.status = ret; + resp.supported_session_types = BIT(DRM_XE_PXP_TYPE_HWDRM); + + if (copy_to_user(query_ptr, &resp, size)) + return -EFAULT; + + return 0; +} + static int (* const xe_query_funcs[])(struct xe_device *xe, struct drm_xe_device_query *query) = { query_engines, @@ -709,6 +737,7 @@ static int (* const xe_query_funcs[])(struct xe_device *xe, query_engine_cycles, query_uc_fw_version, query_oa_units, + query_pxp_status, }; int xe_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 9d53834c4c0a..112fd27f3c75 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -629,6 +629,39 @@ struct drm_xe_query_uc_fw_version { __u64 reserved; }; +/** + * struct drm_xe_query_pxp_status - query if PXP is ready + * + * If PXP is enabled and no fatal error has occurred, the status will be set to + * one of the following values: + * 0: PXP init still in progress + * 1: PXP init complete + * + * If PXP is not enabled or something has gone wrong, the query will be failed + * with one of the following error codes: + * -ENODEV: PXP not supported or disabled; + * -EIO: fatal error occurred during init, so PXP will never be enabled; + * -EINVAL: incorrect value provided as part of the query; + * -EFAULT: error copying the memory between kernel and userspace. + * + * The status can only be 0 in the first few seconds after driver load. If + * everything works as expected, the status will transition to init complete in + * less than 1 second, while in case of errors the driver might take longer to + * start returning an error code, but it should still take less than 10 seconds. + * + * The supported session type bitmask is based on the values in + * enum drm_xe_pxp_session_type. TYPE_NONE is always supported and therefore + * is not reported in the bitmask. + * + */ +struct drm_xe_query_pxp_status { + /** @status: current PXP status */ + __u32 status; + + /** @supported_session_types: bitmask of supported PXP session types */ + __u32 supported_session_types; +}; + /** * struct drm_xe_device_query - Input of &DRM_IOCTL_XE_DEVICE_QUERY - main * structure to query device information @@ -648,6 +681,7 @@ struct drm_xe_query_uc_fw_version { * attributes. * - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY * - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES + * - %DRM_XE_DEVICE_QUERY_PXP_STATUS * * If size is set to 0, the driver fills it with the required size for * the requested type of data to query. If size is equal to the required @@ -700,6 +734,7 @@ struct drm_xe_device_query { #define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES 6 #define DRM_XE_DEVICE_QUERY_UC_FW_VERSION 7 #define DRM_XE_DEVICE_QUERY_OA_UNITS 8 +#define DRM_XE_DEVICE_QUERY_PXP_STATUS 9 /** @query: The type of data to query */ __u32 query; -- cgit v1.2.3-59-g8ed1b From 41a97c4a12947c2786a1680d6839bb72d1c57cec Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:34 -0800 Subject: drm/xe/pxp/uapi: Add API to mark a BO as using PXP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver needs to know if a BO is encrypted with PXP to enable the display decryption at flip time. Furthermore, we want to keep track of the status of the encryption and reject any operation that involves a BO that is encrypted using an old key. There are two points in time where such checks can kick in: 1 - at VM bind time, all operations except for unmapping will be rejected if the key used to encrypt the BO is no longer valid. This check is opt-in via a new VM_BIND flag, to avoid a scenario where a malicious app purposely shares an invalid BO with a non-PXP aware app (such as a compositor). If the VM_BIND was failed, the compositor would be unable to display anything at all. Allowing the bind to go through means that output still works, it just displays garbage data within the bounds of the illegal BO. 2 - at job submission time, if the queue is marked as using PXP, all objects bound to the VM will be checked and the submission will be rejected if any of them was encrypted with a key that is no longer valid. Note that there is no risk of leaking the encrypted data if a user does not opt-in to those checks; the only consequence is that the user will not realize that the encryption key is changed and that the data is no longer valid. v2: Better commnnts and descriptions (John), rebase v3: Properly return the result of key_assign up the stack, do not use xe_bo in display headers (Jani) v4: improve key_instance variable documentation (John) Signed-off-by: Daniele Ceraolo Spurio Cc: Matthew Brost Cc: Thomas Hellström Cc: John Harrison Cc: Jani Nikula Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-11-daniele.ceraolospurio@intel.com --- .../gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h | 12 ++- drivers/gpu/drm/xe/display/intel_bo.c | 2 +- drivers/gpu/drm/xe/xe_bo.c | 98 +++++++++++++++++++++- drivers/gpu/drm/xe/xe_bo.h | 5 ++ drivers/gpu/drm/xe/xe_bo_types.h | 6 ++ drivers/gpu/drm/xe/xe_exec.c | 6 ++ drivers/gpu/drm/xe/xe_pxp.c | 90 ++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp.h | 6 ++ drivers/gpu/drm/xe/xe_pxp_types.h | 11 +++ drivers/gpu/drm/xe/xe_vm.c | 46 +++++++++- drivers/gpu/drm/xe/xe_vm.h | 2 + include/uapi/drm/xe_drm.h | 19 +++++ 12 files changed, 296 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h b/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h index 419e8e926f00..d2eb8e1f6c4b 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h @@ -9,6 +9,8 @@ #include #include +#include "xe_pxp.h" + struct drm_gem_object; struct xe_pxp; @@ -16,7 +18,15 @@ static inline int intel_pxp_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj, bool assign) { - return -ENODEV; + /* + * The assign variable is used in i915 to assign the key to the BO at + * first submission time. In Xe the key is instead assigned at BO + * creation time, so the assign variable must always be false. + */ + if (assign) + return -EINVAL; + + return xe_pxp_obj_key_check(pxp, obj); } #endif diff --git a/drivers/gpu/drm/xe/display/intel_bo.c b/drivers/gpu/drm/xe/display/intel_bo.c index b463f5bd4eed..27437c22bd70 100644 --- a/drivers/gpu/drm/xe/display/intel_bo.c +++ b/drivers/gpu/drm/xe/display/intel_bo.c @@ -25,7 +25,7 @@ bool intel_bo_is_shmem(struct drm_gem_object *obj) bool intel_bo_is_protected(struct drm_gem_object *obj) { - return false; + return xe_bo_is_protected(gem_to_xe_bo(obj)); } void intel_bo_flush_if_display(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index c32201123d44..6812164e1470 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -6,6 +6,7 @@ #include "xe_bo.h" #include +#include #include #include @@ -26,6 +27,7 @@ #include "xe_migrate.h" #include "xe_pm.h" #include "xe_preempt_fence.h" +#include "xe_pxp.h" #include "xe_res_cursor.h" #include "xe_trace_bo.h" #include "xe_ttm_stolen_mgr.h" @@ -2155,6 +2157,93 @@ void xe_bo_vunmap(struct xe_bo *bo) __xe_bo_vunmap(bo); } +static int gem_create_set_pxp_type(struct xe_device *xe, struct xe_bo *bo, u64 value) +{ + if (value == DRM_XE_PXP_TYPE_NONE) + return 0; + + /* we only support DRM_XE_PXP_TYPE_HWDRM for now */ + if (XE_IOCTL_DBG(xe, value != DRM_XE_PXP_TYPE_HWDRM)) + return -EINVAL; + + return xe_pxp_key_assign(xe->pxp, bo); +} + +typedef int (*xe_gem_create_set_property_fn)(struct xe_device *xe, + struct xe_bo *bo, + u64 value); + +static const xe_gem_create_set_property_fn gem_create_set_property_funcs[] = { + [DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY] = gem_create_set_pxp_type, +}; + +static int gem_create_user_ext_set_property(struct xe_device *xe, + struct xe_bo *bo, + u64 extension) +{ + u64 __user *address = u64_to_user_ptr(extension); + struct drm_xe_ext_set_property ext; + int err; + u32 idx; + + err = __copy_from_user(&ext, address, sizeof(ext)); + if (XE_IOCTL_DBG(xe, err)) + return -EFAULT; + + if (XE_IOCTL_DBG(xe, ext.property >= + ARRAY_SIZE(gem_create_set_property_funcs)) || + XE_IOCTL_DBG(xe, ext.pad) || + XE_IOCTL_DBG(xe, ext.property != DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY)) + return -EINVAL; + + idx = array_index_nospec(ext.property, ARRAY_SIZE(gem_create_set_property_funcs)); + if (!gem_create_set_property_funcs[idx]) + return -EINVAL; + + return gem_create_set_property_funcs[idx](xe, bo, ext.value); +} + +typedef int (*xe_gem_create_user_extension_fn)(struct xe_device *xe, + struct xe_bo *bo, + u64 extension); + +static const xe_gem_create_user_extension_fn gem_create_user_extension_funcs[] = { + [DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY] = gem_create_user_ext_set_property, +}; + +#define MAX_USER_EXTENSIONS 16 +static int gem_create_user_extensions(struct xe_device *xe, struct xe_bo *bo, + u64 extensions, int ext_number) +{ + u64 __user *address = u64_to_user_ptr(extensions); + struct drm_xe_user_extension ext; + int err; + u32 idx; + + if (XE_IOCTL_DBG(xe, ext_number >= MAX_USER_EXTENSIONS)) + return -E2BIG; + + err = __copy_from_user(&ext, address, sizeof(ext)); + if (XE_IOCTL_DBG(xe, err)) + return -EFAULT; + + if (XE_IOCTL_DBG(xe, ext.pad) || + XE_IOCTL_DBG(xe, ext.name >= ARRAY_SIZE(gem_create_user_extension_funcs))) + return -EINVAL; + + idx = array_index_nospec(ext.name, + ARRAY_SIZE(gem_create_user_extension_funcs)); + err = gem_create_user_extension_funcs[idx](xe, bo, extensions); + if (XE_IOCTL_DBG(xe, err)) + return err; + + if (ext.next_extension) + return gem_create_user_extensions(xe, bo, ext.next_extension, + ++ext_number); + + return 0; +} + int xe_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { @@ -2167,8 +2256,7 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, u32 handle; int err; - if (XE_IOCTL_DBG(xe, args->extensions) || - XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) || + if (XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) || XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1])) return -EINVAL; @@ -2250,6 +2338,12 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, goto out_vm; } + if (args->extensions) { + err = gem_create_user_extensions(xe, bo, args->extensions, 0); + if (err) + goto out_bulk; + } + err = drm_gem_handle_create(file, &bo->ttm.base, &handle); if (err) goto out_bulk; diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h index 04995c5ced32..f09b9315721b 100644 --- a/drivers/gpu/drm/xe/xe_bo.h +++ b/drivers/gpu/drm/xe/xe_bo.h @@ -186,6 +186,11 @@ static inline bool xe_bo_is_pinned(struct xe_bo *bo) return bo->ttm.pin_count; } +static inline bool xe_bo_is_protected(const struct xe_bo *bo) +{ + return bo->pxp_key_instance; +} + static inline void xe_bo_unpin_map_no_vm(struct xe_bo *bo) { if (likely(bo)) { diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h index 46dc9e4e3e46..60c522866500 100644 --- a/drivers/gpu/drm/xe/xe_bo_types.h +++ b/drivers/gpu/drm/xe/xe_bo_types.h @@ -57,6 +57,12 @@ struct xe_bo { */ struct list_head client_link; #endif + /** + * @pxp_key_instance: PXP key instance this BO was created against. A + * 0 in this variable indicates that the BO does not use PXP encryption. + */ + u32 pxp_key_instance; + /** @freed: List node for delayed put. */ struct llist_node freed; /** @update_index: Update index if PT BO */ diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c index df8ce550deb4..b75adfc99fb7 100644 --- a/drivers/gpu/drm/xe/xe_exec.c +++ b/drivers/gpu/drm/xe/xe_exec.c @@ -262,6 +262,12 @@ retry: goto err_exec; } + if (xe_exec_queue_uses_pxp(q)) { + err = xe_vm_validate_protected(q->vm); + if (err) + goto err_exec; + } + job = xe_sched_job_create(q, xe_exec_queue_is_parallel(q) ? addresses : &args->address); if (IS_ERR(job)) { diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 24aef5c0f04a..8060b4050be8 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -8,6 +8,8 @@ #include #include +#include "xe_bo.h" +#include "xe_bo_types.h" #include "xe_device_types.h" #include "xe_exec_queue.h" #include "xe_force_wake.h" @@ -185,6 +187,9 @@ static void pxp_terminate(struct xe_pxp *pxp) pxp_invalidate_queues(pxp); + if (pxp->status == XE_PXP_ACTIVE) + pxp->key_instance++; + /* * If we have a termination already in progress, we need to wait for * it to complete before queueing another one. Once the first @@ -385,6 +390,8 @@ int xe_pxp_init(struct xe_device *xe) pxp->xe = xe; pxp->gt = gt; + pxp->key_instance = 1; + /* * we'll use the completions to check if there is an action pending, * so we start them as completed and we reinit it when an action is @@ -689,3 +696,86 @@ static void pxp_invalidate_queues(struct xe_pxp *pxp) spin_unlock_irq(&pxp->queues.lock); } + +/** + * xe_pxp_key_assign - mark a BO as using the current PXP key iteration + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * @bo: the BO to mark + * + * Returns: -ENODEV if PXP is disabled, 0 otherwise. + */ +int xe_pxp_key_assign(struct xe_pxp *pxp, struct xe_bo *bo) +{ + if (!xe_pxp_is_enabled(pxp)) + return -ENODEV; + + xe_assert(pxp->xe, !bo->pxp_key_instance); + + /* + * Note that the PXP key handling is inherently racey, because the key + * can theoretically change at any time (although it's unlikely to do + * so without triggers), even right after we copy it. Taking a lock + * wouldn't help because the value might still change as soon as we + * release the lock. + * Userspace needs to handle the fact that their BOs can go invalid at + * any point. + */ + bo->pxp_key_instance = pxp->key_instance; + + return 0; +} + +/** + * xe_pxp_bo_key_check - check if the key used by a xe_bo is valid + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * @bo: the BO we want to check + * + * Checks whether a BO was encrypted with the current key or an obsolete one. + * + * Returns: 0 if the key is valid, -ENODEV if PXP is disabled, -EINVAL if the + * BO is not using PXP, -ENOEXEC if the key is not valid. + */ +int xe_pxp_bo_key_check(struct xe_pxp *pxp, struct xe_bo *bo) +{ + if (!xe_pxp_is_enabled(pxp)) + return -ENODEV; + + if (!xe_bo_is_protected(bo)) + return -EINVAL; + + xe_assert(pxp->xe, bo->pxp_key_instance); + + /* + * Note that the PXP key handling is inherently racey, because the key + * can theoretically change at any time (although it's unlikely to do + * so without triggers), even right after we check it. Taking a lock + * wouldn't help because the value might still change as soon as we + * release the lock. + * We mitigate the risk by checking the key at multiple points (on each + * submission involving the BO and right before flipping it on the + * display), but there is still a very small chance that we could + * operate on an invalid BO for a single submission or a single frame + * flip. This is a compromise made to protect the encrypted data (which + * is what the key termination is for). + */ + if (bo->pxp_key_instance != pxp->key_instance) + return -ENOEXEC; + + return 0; +} + +/** + * xe_pxp_obj_key_check - check if the key used by a drm_gem_obj is valid + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * @obj: the drm_gem_obj we want to check + * + * Checks whether a drm_gem_obj was encrypted with the current key or an + * obsolete one. + * + * Returns: 0 if the key is valid, -ENODEV if PXP is disabled, -EINVAL if the + * obj is not using PXP, -ENOEXEC if the key is not valid. + */ +int xe_pxp_obj_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj) +{ + return xe_pxp_bo_key_check(pxp, gem_to_xe_bo(obj)); +} diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index 868813cc84b9..3dd70eac9da6 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -8,6 +8,8 @@ #include +struct drm_gem_object; +struct xe_bo; struct xe_device; struct xe_exec_queue; struct xe_pxp; @@ -23,4 +25,8 @@ int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 t int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q); void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q); +int xe_pxp_key_assign(struct xe_pxp *pxp, struct xe_bo *bo); +int xe_pxp_bo_key_check(struct xe_pxp *pxp, struct xe_bo *bo); +int xe_pxp_obj_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj); + #endif /* __XE_PXP_H__ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h index bd741720f67d..8e4569f0173d 100644 --- a/drivers/gpu/drm/xe/xe_pxp_types.h +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -112,6 +112,17 @@ struct xe_pxp { /** @queues.list: list of exec_queues that use PXP */ struct list_head list; } queues; + + /** + * @key_instance: keep track of the current iteration of the PXP key. + * Note that, due to the time needed for PXP termination and re-start + * to complete, the minimum time between 2 subsequent increases of this + * variable is 50ms, and even that only if there is a continuous attack; + * normal behavior is for this to increase much much slower than that. + * This means that we don't expect this to ever wrap and don't implement + * that case in the code. + */ + u32 key_instance; }; #endif /* __XE_PXP_TYPES_H__ */ diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index b9270d059e18..d664f2e418b2 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -33,6 +33,7 @@ #include "xe_pm.h" #include "xe_preempt_fence.h" #include "xe_pt.h" +#include "xe_pxp.h" #include "xe_res_cursor.h" #include "xe_sync.h" #include "xe_trace_bo.h" @@ -2726,7 +2727,8 @@ ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_execute, ERRNO); (DRM_XE_VM_BIND_FLAG_READONLY | \ DRM_XE_VM_BIND_FLAG_IMMEDIATE | \ DRM_XE_VM_BIND_FLAG_NULL | \ - DRM_XE_VM_BIND_FLAG_DUMPABLE) + DRM_XE_VM_BIND_FLAG_DUMPABLE | \ + DRM_XE_VM_BIND_FLAG_CHECK_PXP) #ifdef TEST_VM_OPS_ERROR #define SUPPORTED_FLAGS (SUPPORTED_FLAGS_STUB | FORCE_OP_ERROR) @@ -2889,7 +2891,7 @@ static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm, static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, u64 addr, u64 range, u64 obj_offset, - u16 pat_index) + u16 pat_index, u32 op, u32 bind_flags) { u16 coh_mode; @@ -2933,6 +2935,12 @@ static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, return -EINVAL; } + /* If a BO is protected it can only be mapped if the key is still valid */ + if ((bind_flags & DRM_XE_VM_BIND_FLAG_CHECK_PXP) && xe_bo_is_protected(bo) && + op != DRM_XE_VM_BIND_OP_UNMAP && op != DRM_XE_VM_BIND_OP_UNMAP_ALL) + if (XE_IOCTL_DBG(xe, xe_pxp_bo_key_check(xe->pxp, bo) != 0)) + return -ENOEXEC; + return 0; } @@ -3022,6 +3030,8 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) u32 obj = bind_ops[i].obj; u64 obj_offset = bind_ops[i].obj_offset; u16 pat_index = bind_ops[i].pat_index; + u32 op = bind_ops[i].op; + u32 bind_flags = bind_ops[i].flags; if (!obj) continue; @@ -3034,7 +3044,8 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) bos[i] = gem_to_xe_bo(gem_obj); err = xe_vm_bind_ioctl_validate_bo(xe, bos[i], addr, range, - obj_offset, pat_index); + obj_offset, pat_index, op, + bind_flags); if (err) goto put_obj; } @@ -3334,6 +3345,35 @@ wait: return ret; } +int xe_vm_validate_protected(struct xe_vm *vm) +{ + struct drm_gpuva *gpuva; + int err = 0; + + if (!vm) + return -ENODEV; + + mutex_lock(&vm->snap_mutex); + + drm_gpuvm_for_each_va(gpuva, &vm->gpuvm) { + struct xe_vma *vma = gpuva_to_vma(gpuva); + struct xe_bo *bo = vma->gpuva.gem.obj ? + gem_to_xe_bo(vma->gpuva.gem.obj) : NULL; + + if (!bo) + continue; + + if (xe_bo_is_protected(bo)) { + err = xe_pxp_bo_key_check(vm->xe->pxp, bo); + if (err) + break; + } + } + + mutex_unlock(&vm->snap_mutex); + return err; +} + struct xe_vm_snapshot { unsigned long num_snaps; struct { diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 0a2fa6c0815b..f66075f8a6fe 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -215,6 +215,8 @@ struct dma_fence *xe_vma_rebind(struct xe_vm *vm, struct xe_vma *vma, int xe_vm_invalidate_vma(struct xe_vma *vma); +int xe_vm_validate_protected(struct xe_vm *vm); + static inline void xe_vm_queue_rebind_worker(struct xe_vm *vm) { xe_assert(vm->xe, xe_vm_in_preempt_fence_mode(vm)); diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 112fd27f3c75..892f54d3aa09 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -778,8 +778,23 @@ struct drm_xe_device_query { * - %DRM_XE_GEM_CPU_CACHING_WC - Allocate the pages as write-combined. This * is uncached. Scanout surfaces should likely use this. All objects * that can be placed in VRAM must use this. + * + * This ioctl supports setting the following properties via the + * %DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY extension, which uses the + * generic @drm_xe_ext_set_property struct: + * + * - %DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE - set the type of PXP session + * this object will be used with. Valid values are listed in enum + * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so + * there is no need to explicitly set that. Objects used with session of type + * %DRM_XE_PXP_TYPE_HWDRM will be marked as invalid if a PXP invalidation + * event occurs after their creation. Attempting to flip an invalid object + * will cause a black frame to be displayed instead. Submissions with invalid + * objects mapped in the VM will be rejected. */ struct drm_xe_gem_create { +#define DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY 0 +#define DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE 0 /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; @@ -968,6 +983,9 @@ struct drm_xe_vm_destroy { * will only be valid for DRM_XE_VM_BIND_OP_MAP operations, the BO * handle MBZ, and the BO offset MBZ. This flag is intended to * implement VK sparse bindings. + * - %DRM_XE_VM_BIND_FLAG_CHECK_PXP - If the object is encrypted via PXP, + * reject the binding if the encryption key is no longer valid. This + * flag has no effect on BOs that are not marked as using PXP. */ struct drm_xe_vm_bind_op { /** @extensions: Pointer to the first extension struct, if any */ @@ -1058,6 +1076,7 @@ struct drm_xe_vm_bind_op { #define DRM_XE_VM_BIND_FLAG_IMMEDIATE (1 << 1) #define DRM_XE_VM_BIND_FLAG_NULL (1 << 2) #define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3) +#define DRM_XE_VM_BIND_FLAG_CHECK_PXP (1 << 4) /** @flags: Bind flags */ __u32 flags; -- cgit v1.2.3-59-g8ed1b From 51462211f4a920687ae51823f6a8b0f499546bcc Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:35 -0800 Subject: drm/xe/pxp: add PXP PM support The HW suspend flow kills all PXP HWDRM sessions, so we need to mark all the queues and BOs as invalid and do a full termination when PXP is next used. v2: rebase v3: rebase on new status flow, defer termination to next PXP use as it makes things much easier and allows us to use the same function for all types of suspend. v4: fix the documentation of the suspend function (John) Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-12-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pm.c | 39 +++++++++--- drivers/gpu/drm/xe/xe_pxp.c | 129 ++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_pxp.h | 3 + drivers/gpu/drm/xe/xe_pxp_types.h | 7 +++ 4 files changed, 165 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index c9cc0c091dfd..35dd1757b40b 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -22,6 +22,7 @@ #include "xe_guc.h" #include "xe_irq.h" #include "xe_pcode.h" +#include "xe_pxp.h" #include "xe_trace.h" #include "xe_wa.h" @@ -122,6 +123,10 @@ int xe_pm_suspend(struct xe_device *xe) drm_dbg(&xe->drm, "Suspending device\n"); trace_xe_pm_suspend(xe, __builtin_return_address(0)); + err = xe_pxp_pm_suspend(xe->pxp); + if (err) + goto err; + for_each_gt(gt, xe, id) xe_gt_suspend_prepare(gt); @@ -130,14 +135,12 @@ int xe_pm_suspend(struct xe_device *xe) /* FIXME: Super racey... */ err = xe_bo_evict_all(xe); if (err) - goto err; + goto err_pxp; for_each_gt(gt, xe, id) { err = xe_gt_suspend(gt); - if (err) { - xe_display_pm_resume(xe); - goto err; - } + if (err) + goto err_display; } xe_irq_suspend(xe); @@ -146,6 +149,11 @@ int xe_pm_suspend(struct xe_device *xe) drm_dbg(&xe->drm, "Device suspended\n"); return 0; + +err_display: + xe_display_pm_resume(xe); +err_pxp: + xe_pxp_pm_resume(xe->pxp); err: drm_dbg(&xe->drm, "Device suspend failed %d\n", err); return err; @@ -195,6 +203,8 @@ int xe_pm_resume(struct xe_device *xe) if (err) goto err; + xe_pxp_pm_resume(xe->pxp); + drm_dbg(&xe->drm, "Device resumed\n"); return 0; err: @@ -389,6 +399,10 @@ int xe_pm_runtime_suspend(struct xe_device *xe) */ xe_rpm_lockmap_acquire(xe); + err = xe_pxp_pm_suspend(xe->pxp); + if (err) + goto out; + /* * Applying lock for entire list op as xe_ttm_bo_destroy and xe_bo_move_notify * also checks and deletes bo entry from user fault list. @@ -404,22 +418,27 @@ int xe_pm_runtime_suspend(struct xe_device *xe) if (xe->d3cold.allowed) { err = xe_bo_evict_all(xe); if (err) - goto out; + goto out_resume; } for_each_gt(gt, xe, id) { err = xe_gt_suspend(gt); if (err) - goto out; + goto out_resume; } xe_irq_suspend(xe); xe_display_pm_runtime_suspend_late(xe); + xe_rpm_lockmap_release(xe); + xe_pm_write_callback_task(xe, NULL); + return 0; + +out_resume: + xe_display_pm_runtime_resume(xe); + xe_pxp_pm_resume(xe->pxp); out: - if (err) - xe_display_pm_runtime_resume(xe); xe_rpm_lockmap_release(xe); xe_pm_write_callback_task(xe, NULL); return err; @@ -472,6 +491,8 @@ int xe_pm_runtime_resume(struct xe_device *xe) goto out; } + xe_pxp_pm_resume(xe->pxp); + out: xe_rpm_lockmap_release(xe); xe_pm_write_callback_task(xe, NULL); diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 8060b4050be8..5e7a1688a771 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -132,6 +132,14 @@ static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play) static void pxp_invalidate_queues(struct xe_pxp *pxp); +static void pxp_invalidate_state(struct xe_pxp *pxp) +{ + pxp_invalidate_queues(pxp); + + if (pxp->status == XE_PXP_ACTIVE) + pxp->key_instance++; +} + static int pxp_terminate_hw(struct xe_pxp *pxp) { struct xe_gt *gt = pxp->gt; @@ -185,10 +193,16 @@ static void pxp_terminate(struct xe_pxp *pxp) mutex_lock(&pxp->mutex); - pxp_invalidate_queues(pxp); + pxp_invalidate_state(pxp); - if (pxp->status == XE_PXP_ACTIVE) - pxp->key_instance++; + /* + * we'll mark the status as needing termination on resume, so no need to + * emit a termination now. + */ + if (pxp->status == XE_PXP_SUSPENDED) { + mutex_unlock(&pxp->mutex); + return; + } /* * If we have a termination already in progress, we need to wait for @@ -219,11 +233,13 @@ static void pxp_terminate(struct xe_pxp *pxp) static void pxp_terminate_complete(struct xe_pxp *pxp) { /* - * We expect PXP to be in one of 2 states when we get here: + * We expect PXP to be in one of 3 states when we get here: * - XE_PXP_TERMINATION_IN_PROGRESS: a single termination event was * requested and it is now completing, so we're ready to start. * - XE_PXP_NEEDS_ADDITIONAL_TERMINATION: a second termination was * requested while the first one was still being processed. + * - XE_PXP_SUSPENDED: PXP is now suspended, so we defer everything to + * when we come back on resume. */ mutex_lock(&pxp->mutex); @@ -234,6 +250,9 @@ static void pxp_terminate_complete(struct xe_pxp *pxp) case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: pxp->status = XE_PXP_NEEDS_TERMINATION; break; + case XE_PXP_SUSPENDED: + /* Nothing to do */ + break; default: drm_err(&pxp->xe->drm, "PXP termination complete while status was %u\n", @@ -391,6 +410,7 @@ int xe_pxp_init(struct xe_device *xe) pxp->gt = gt; pxp->key_instance = 1; + pxp->last_suspend_key_instance = 1; /* * we'll use the completions to check if there is an action pending, @@ -574,6 +594,7 @@ wait_for_idle: XE_WARN_ON(completion_done(&pxp->termination)); mutex_unlock(&pxp->mutex); goto wait_for_idle; + case XE_PXP_SUSPENDED: default: drm_err(&pxp->xe->drm, "unexpected state during PXP start: %u\n", pxp->status); ret = -EIO; @@ -779,3 +800,103 @@ int xe_pxp_obj_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj) { return xe_pxp_bo_key_check(pxp, gem_to_xe_bo(obj)); } + +/** + * xe_pxp_pm_suspend - prepare PXP for HW suspend + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + * + * Makes sure all PXP actions have completed and invalidates all PXP queues + * and objects before we go into a suspend state. + * + * Returns: 0 if successful, a negative errno value otherwise. + */ +int xe_pxp_pm_suspend(struct xe_pxp *pxp) +{ + int ret = 0; + + if (!xe_pxp_is_enabled(pxp)) + return 0; + +wait_for_activation: + if (!wait_for_completion_timeout(&pxp->activation, + msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) + ret = -ETIMEDOUT; + + mutex_lock(&pxp->mutex); + + switch (pxp->status) { + case XE_PXP_ERROR: + case XE_PXP_READY_TO_START: + case XE_PXP_SUSPENDED: + case XE_PXP_TERMINATION_IN_PROGRESS: + case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: + /* + * If PXP is not running there is nothing to cleanup. If there + * is a termination pending then no need to issue another one. + */ + break; + case XE_PXP_START_IN_PROGRESS: + mutex_unlock(&pxp->mutex); + goto wait_for_activation; + case XE_PXP_NEEDS_TERMINATION: + /* If PXP was never used we can skip the cleanup */ + if (pxp->key_instance == pxp->last_suspend_key_instance) + break; + fallthrough; + case XE_PXP_ACTIVE: + pxp_invalidate_state(pxp); + break; + default: + drm_err(&pxp->xe->drm, "unexpected state during PXP suspend: %u", + pxp->status); + ret = -EIO; + goto out; + } + + /* + * We set this even if we were in error state, hoping the suspend clears + * the error. Worse case we fail again and go in error state again. + */ + pxp->status = XE_PXP_SUSPENDED; + + mutex_unlock(&pxp->mutex); + + /* + * if there is a termination in progress, wait for it. + * We need to wait outside the lock because the completion is done from + * within the lock + */ + if (!wait_for_completion_timeout(&pxp->termination, + msecs_to_jiffies(PXP_TERMINATION_TIMEOUT_MS))) + ret = -ETIMEDOUT; + + pxp->last_suspend_key_instance = pxp->key_instance; + +out: + return ret; +} + +/** + * xe_pxp_pm_resume - re-init PXP after HW suspend + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) + */ +void xe_pxp_pm_resume(struct xe_pxp *pxp) +{ + int err; + + if (!xe_pxp_is_enabled(pxp)) + return; + + err = kcr_pxp_enable(pxp); + + mutex_lock(&pxp->mutex); + + xe_assert(pxp->xe, pxp->status == XE_PXP_SUSPENDED); + + if (err) + pxp->status = XE_PXP_ERROR; + else + pxp->status = XE_PXP_NEEDS_TERMINATION; + + mutex_unlock(&pxp->mutex); +} diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index 3dd70eac9da6..546b156d63aa 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -21,6 +21,9 @@ int xe_pxp_get_readiness_status(struct xe_pxp *pxp); int xe_pxp_init(struct xe_device *xe); void xe_pxp_irq_handler(struct xe_device *xe, u16 iir); +int xe_pxp_pm_suspend(struct xe_pxp *pxp); +void xe_pxp_pm_resume(struct xe_pxp *pxp); + int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 type); int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q); void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q); diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h index 8e4569f0173d..53e9d48d10fb 100644 --- a/drivers/gpu/drm/xe/xe_pxp_types.h +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -27,6 +27,7 @@ enum xe_pxp_status { XE_PXP_READY_TO_START, XE_PXP_START_IN_PROGRESS, XE_PXP_ACTIVE, + XE_PXP_SUSPENDED, }; /** @@ -123,6 +124,12 @@ struct xe_pxp { * that case in the code. */ u32 key_instance; + /** + * @last_suspend_key_instance: value of key_instance at the last + * suspend. Used to check if any PXP session has been created between + * suspend cycles. + */ + u32 last_suspend_key_instance; }; #endif /* __XE_PXP_TYPES_H__ */ -- cgit v1.2.3-59-g8ed1b From 385a8015b21469f249cdf30453f2c93d32405aa9 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:36 -0800 Subject: drm/xe/pxp: Add PXP debugfs support This patch introduces 2 PXP debugfs entries: - info: prints the current PXP status and key instance - terminate: simulate a termination interrupt The first one is useful for debug, while the second one can be used for testing the termination flow. v2: move the info prints inside the lock (John) Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-13-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_debugfs.c | 3 + drivers/gpu/drm/xe/xe_pxp_debugfs.c | 120 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pxp_debugfs.h | 13 ++++ 4 files changed, 137 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_pxp_debugfs.c create mode 100644 drivers/gpu/drm/xe/xe_pxp_debugfs.h (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 720d13c16fa5..be73362ef334 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -88,6 +88,7 @@ xe-y += xe_bb.o \ xe_pt.o \ xe_pt_walk.o \ xe_pxp.o \ + xe_pxp_debugfs.o \ xe_pxp_submit.o \ xe_query.o \ xe_range_fence.o \ diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index 492b4877433f..56cb3788e752 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -18,6 +18,7 @@ #include "xe_gt_printk.h" #include "xe_guc_ads.h" #include "xe_pm.h" +#include "xe_pxp_debugfs.h" #include "xe_sriov.h" #include "xe_step.h" @@ -230,5 +231,7 @@ void xe_debugfs_register(struct xe_device *xe) for_each_gt(gt, xe, id) xe_gt_debugfs_register(gt); + xe_pxp_debugfs_register(xe->pxp); + fault_create_debugfs_attr("fail_gt_reset", root, >_reset_failure); } diff --git a/drivers/gpu/drm/xe/xe_pxp_debugfs.c b/drivers/gpu/drm/xe/xe_pxp_debugfs.c new file mode 100644 index 000000000000..ccfbacf08efc --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pxp_debugfs.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include "xe_pxp_debugfs.h" + +#include + +#include +#include +#include + +#include "xe_device.h" +#include "xe_pxp.h" +#include "xe_pxp_types.h" +#include "regs/xe_irq_regs.h" + +static struct xe_pxp *node_to_pxp(struct drm_info_node *node) +{ + return node->info_ent->data; +} + +static const char *pxp_status_to_str(struct xe_pxp *pxp) +{ + lockdep_assert_held(&pxp->mutex); + + switch (pxp->status) { + case XE_PXP_ERROR: + return "error"; + case XE_PXP_NEEDS_TERMINATION: + return "needs termination"; + case XE_PXP_TERMINATION_IN_PROGRESS: + return "termination in progress"; + case XE_PXP_READY_TO_START: + return "ready to start"; + case XE_PXP_ACTIVE: + return "active"; + case XE_PXP_SUSPENDED: + return "suspended"; + default: + return "unknown"; + } +}; + +static int pxp_info(struct seq_file *m, void *data) +{ + struct xe_pxp *pxp = node_to_pxp(m->private); + struct drm_printer p = drm_seq_file_printer(m); + const char *status; + + if (!xe_pxp_is_enabled(pxp)) + return -ENODEV; + + mutex_lock(&pxp->mutex); + status = pxp_status_to_str(pxp); + + drm_printf(&p, "status: %s\n", status); + drm_printf(&p, "instance counter: %u\n", pxp->key_instance); + mutex_unlock(&pxp->mutex); + + return 0; +} + +static int pxp_terminate(struct seq_file *m, void *data) +{ + struct xe_pxp *pxp = node_to_pxp(m->private); + struct drm_printer p = drm_seq_file_printer(m); + + if (!xe_pxp_is_enabled(pxp)) + return -ENODEV; + + /* simulate a termination interrupt */ + spin_lock_irq(&pxp->xe->irq.lock); + xe_pxp_irq_handler(pxp->xe, KCR_PXP_STATE_TERMINATED_INTERRUPT); + spin_unlock_irq(&pxp->xe->irq.lock); + + drm_printf(&p, "PXP termination queued\n"); + + return 0; +} + +static const struct drm_info_list debugfs_list[] = { + {"info", pxp_info, 0}, + {"terminate", pxp_terminate, 0}, +}; + +void xe_pxp_debugfs_register(struct xe_pxp *pxp) +{ + struct drm_minor *minor; + struct drm_info_list *local; + struct dentry *root; + int i; + + if (!xe_pxp_is_enabled(pxp)) + return; + + minor = pxp->xe->drm.primary; + if (!minor->debugfs_root) + return; + +#define DEBUGFS_SIZE (ARRAY_SIZE(debugfs_list) * sizeof(struct drm_info_list)) + local = drmm_kmalloc(&pxp->xe->drm, DEBUGFS_SIZE, GFP_KERNEL); + if (!local) + return; + + memcpy(local, debugfs_list, DEBUGFS_SIZE); +#undef DEBUGFS_SIZE + + for (i = 0; i < ARRAY_SIZE(debugfs_list); ++i) + local[i].data = pxp; + + root = debugfs_create_dir("pxp", minor->debugfs_root); + if (IS_ERR(root)) + return; + + drm_debugfs_create_files(local, + ARRAY_SIZE(debugfs_list), + root, minor); +} diff --git a/drivers/gpu/drm/xe/xe_pxp_debugfs.h b/drivers/gpu/drm/xe/xe_pxp_debugfs.h new file mode 100644 index 000000000000..988466aad50b --- /dev/null +++ b/drivers/gpu/drm/xe/xe_pxp_debugfs.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __XE_PXP_DEBUGFS_H__ +#define __XE_PXP_DEBUGFS_H__ + +struct xe_pxp; + +void xe_pxp_debugfs_register(struct xe_pxp *pxp); + +#endif /* __XE_PXP_DEBUGFS_H__ */ -- cgit v1.2.3-59-g8ed1b From 492f8d2030bec7ab6d0adf7f41808d73871f86e7 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 29 Jan 2025 09:41:37 -0800 Subject: drm/xe/pxp: Enable PXP for MTL and LNL Now that are the pieces are there, we can turn the feature on. Signed-off-by: Daniele Ceraolo Spurio Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-14-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 0a6e58d55682..feb46a707281 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -333,11 +333,13 @@ static const struct xe_device_desc mtl_desc = { .require_force_probe = true, PLATFORM(METEORLAKE), .has_display = true, + .has_pxp = true, }; static const struct xe_device_desc lnl_desc = { PLATFORM(LUNARLAKE), .has_display = true, + .has_pxp = true, }; static const struct xe_device_desc bmg_desc = { -- cgit v1.2.3-59-g8ed1b From e4afdef60562014bc4a5c74384cfe9de84590ca5 Mon Sep 17 00:00:00 2001 From: Sai Teja Pottumuttu Date: Thu, 30 Jan 2025 14:28:03 +0530 Subject: drm/xe: Refactor dma_mask_size dma_mask_size is more related to the platform than the GT IP. Thus move it to platform descriptors. v2: - Rebase Signed-off-by: Sai Teja Pottumuttu Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20250130085804.4136497-2-sai.teja.pottumuttu@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pci.c | 22 ++++++++++++++++------ drivers/gpu/drm/xe/xe_pci_types.h | 1 - 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index feb46a707281..38e6ba091ea5 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -55,6 +55,8 @@ struct xe_device_desc { enum xe_platform platform; + u8 dma_mask_size; + u8 require_force_probe:1; u8 is_dgfx:1; @@ -85,7 +87,6 @@ static const struct xe_graphics_desc graphics_xelp = { .hw_engine_mask = BIT(XE_HW_ENGINE_RCS0) | BIT(XE_HW_ENGINE_BCS0), - .dma_mask_size = 39, .va_bits = 48, .vm_max_level = 3, }; @@ -97,14 +98,12 @@ static const struct xe_graphics_desc graphics_xelpp = { .hw_engine_mask = BIT(XE_HW_ENGINE_RCS0) | BIT(XE_HW_ENGINE_BCS0), - .dma_mask_size = 39, .va_bits = 48, .vm_max_level = 3, }; #define XE_HP_FEATURES \ .has_range_tlb_invalidation = true, \ - .dma_mask_size = 46, \ .va_bits = 48, \ .vm_max_level = 3 @@ -139,7 +138,6 @@ static const struct xe_graphics_desc graphics_xehpc = { BIT(XE_HW_ENGINE_CCS2) | BIT(XE_HW_ENGINE_CCS3), XE_HP_FEATURES, - .dma_mask_size = 52, .max_remote_tiles = 1, .va_bits = 57, .vm_max_level = 4, @@ -160,7 +158,6 @@ static const struct xe_graphics_desc graphics_xelpg = { }; #define XE2_GFX_FEATURES \ - .dma_mask_size = 46, \ .has_asid = 1, \ .has_atomic_enable_pte_bit = 1, \ .has_flat_ccs = 1, \ @@ -220,6 +217,7 @@ static const struct xe_device_desc tgl_desc = { .graphics = &graphics_xelp, .media = &media_xem, PLATFORM(TIGERLAKE), + .dma_mask_size = 39, .has_display = true, .has_llc = true, .require_force_probe = true, @@ -229,6 +227,7 @@ static const struct xe_device_desc rkl_desc = { .graphics = &graphics_xelp, .media = &media_xem, PLATFORM(ROCKETLAKE), + .dma_mask_size = 39, .has_display = true, .has_llc = true, .require_force_probe = true, @@ -240,6 +239,7 @@ static const struct xe_device_desc adl_s_desc = { .graphics = &graphics_xelp, .media = &media_xem, PLATFORM(ALDERLAKE_S), + .dma_mask_size = 39, .has_display = true, .has_llc = true, .require_force_probe = true, @@ -255,6 +255,7 @@ static const struct xe_device_desc adl_p_desc = { .graphics = &graphics_xelp, .media = &media_xem, PLATFORM(ALDERLAKE_P), + .dma_mask_size = 39, .has_display = true, .has_llc = true, .require_force_probe = true, @@ -268,6 +269,7 @@ static const struct xe_device_desc adl_n_desc = { .graphics = &graphics_xelp, .media = &media_xem, PLATFORM(ALDERLAKE_N), + .dma_mask_size = 39, .has_display = true, .has_llc = true, .require_force_probe = true, @@ -281,6 +283,7 @@ static const struct xe_device_desc dg1_desc = { .media = &media_xem, DGFX_FEATURES, PLATFORM(DG1), + .dma_mask_size = 39, .has_display = true, .has_heci_gscfi = 1, .require_force_probe = true, @@ -304,6 +307,7 @@ static const u16 dg2_g12_ids[] = { INTEL_DG2_G12_IDS(NOP), 0 }; static const struct xe_device_desc ats_m_desc = { .graphics = &graphics_xehpg, .media = &media_xehpm, + .dma_mask_size = 46, .require_force_probe = true, DG2_FEATURES, @@ -313,6 +317,7 @@ static const struct xe_device_desc ats_m_desc = { static const struct xe_device_desc dg2_desc = { .graphics = &graphics_xehpg, .media = &media_xehpm, + .dma_mask_size = 46, .require_force_probe = true, DG2_FEATURES, @@ -323,6 +328,7 @@ static const __maybe_unused struct xe_device_desc pvc_desc = { .graphics = &graphics_xehpc, DGFX_FEATURES, PLATFORM(PVC), + .dma_mask_size = 52, .has_display = false, .has_heci_gscfi = 1, .require_force_probe = true, @@ -332,12 +338,14 @@ static const struct xe_device_desc mtl_desc = { /* .graphics and .media determined via GMD_ID */ .require_force_probe = true, PLATFORM(METEORLAKE), + .dma_mask_size = 46, .has_display = true, .has_pxp = true, }; static const struct xe_device_desc lnl_desc = { PLATFORM(LUNARLAKE), + .dma_mask_size = 46, .has_display = true, .has_pxp = true, }; @@ -345,12 +353,14 @@ static const struct xe_device_desc lnl_desc = { static const struct xe_device_desc bmg_desc = { DGFX_FEATURES, PLATFORM(BATTLEMAGE), + .dma_mask_size = 46, .has_display = true, .has_heci_cscfi = 1, }; static const struct xe_device_desc ptl_desc = { PLATFORM(PANTHERLAKE), + .dma_mask_size = 46, .has_display = true, .require_force_probe = true, }; @@ -617,6 +627,7 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.subplatform = subplatform_desc ? subplatform_desc->subplatform : XE_SUBPLATFORM_NONE; + xe->info.dma_mask_size = desc->dma_mask_size; xe->info.is_dgfx = desc->is_dgfx; xe->info.has_heci_gscfi = desc->has_heci_gscfi; xe->info.has_heci_cscfi = desc->has_heci_cscfi; @@ -682,7 +693,6 @@ static int xe_info_init(struct xe_device *xe, xe->info.graphics_name = graphics_desc->name; xe->info.media_name = media_desc ? media_desc->name : "none"; - xe->info.dma_mask_size = graphics_desc->dma_mask_size; xe->info.vram_flags = graphics_desc->vram_flags; xe->info.va_bits = graphics_desc->va_bits; xe->info.vm_max_level = graphics_desc->vm_max_level; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 873efec5cdee..7437415a54d5 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -13,7 +13,6 @@ struct xe_graphics_desc { u8 ver; u8 rel; - u8 dma_mask_size; /* available DMA address bits */ u8 va_bits; u8 vm_max_level; u8 vram_flags; -- cgit v1.2.3-59-g8ed1b From 206fa53fe1f1f73eae61c4330aa31dd6393d959e Mon Sep 17 00:00:00 2001 From: Sai Teja Pottumuttu Date: Thu, 30 Jan 2025 14:28:04 +0530 Subject: drm/xe: Refactor max_remote_tiles max_remote_tiles is more related to the platform than the GT IP. Thus move it to platform descriptor from graphics descriptor. Note that the FIXME is no more required, thus it can be dropped. v2: Rebase v3: Change the position of comment (MattR) Signed-off-by: Sai Teja Pottumuttu Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20250130085804.4136497-3-sai.teja.pottumuttu@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pci.c | 21 +++++++++------------ drivers/gpu/drm/xe/xe_pci_types.h | 2 -- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 38e6ba091ea5..cfa1ad7a1f2d 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -56,6 +56,7 @@ struct xe_device_desc { enum xe_platform platform; u8 dma_mask_size; + u8 max_remote_tiles:2; u8 require_force_probe:1; u8 is_dgfx:1; @@ -138,7 +139,6 @@ static const struct xe_graphics_desc graphics_xehpc = { BIT(XE_HW_ENGINE_CCS2) | BIT(XE_HW_ENGINE_CCS3), XE_HP_FEATURES, - .max_remote_tiles = 1, .va_bits = 57, .vm_max_level = 4, .vram_flags = XE_VRAM_FLAGS_NEED64K, @@ -331,6 +331,7 @@ static const __maybe_unused struct xe_device_desc pvc_desc = { .dma_mask_size = 52, .has_display = false, .has_heci_gscfi = 1, + .max_remote_tiles = 1, .require_force_probe = true, }; @@ -641,6 +642,7 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.probe_display = IS_ENABLED(CONFIG_DRM_XE_DISPLAY) && xe_modparam.probe_display && desc->has_display; + xe->info.tile_count = 1 + desc->max_remote_tiles; err = xe_tile_init_early(xe_device_get_root_tile(xe), xe, 0); if (err) @@ -707,17 +709,6 @@ static int xe_info_init(struct xe_device *xe, xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation; xe->info.has_usm = graphics_desc->has_usm; - /* - * All platforms have at least one primary GT. Any platform with media - * version 13 or higher has an additional dedicated media GT. And - * depending on the graphics IP there may be additional "remote tiles." - * All of these together determine the overall GT count. - * - * FIXME: 'tile_count' here is misnamed since the rest of the driver - * treats it as the number of GTs rather than just the number of tiles. - */ - xe->info.tile_count = 1 + graphics_desc->max_remote_tiles; - for_each_remote_tile(tile, xe, id) { int err; @@ -726,6 +717,12 @@ static int xe_info_init(struct xe_device *xe, return err; } + /* + * All platforms have at least one primary GT. Any platform with media + * version 13 or higher has an additional dedicated media GT. And + * depending on the graphics IP there may be additional "remote tiles." + * All of these together determine the overall GT count. + */ for_each_tile(tile, xe, id) { gt = tile->primary_gt; gt->info.id = xe->info.gt_count++; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 7437415a54d5..b96423844952 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -19,8 +19,6 @@ struct xe_graphics_desc { u64 hw_engine_mask; /* hardware engines provided by graphics IP */ - u8 max_remote_tiles:2; - u8 has_asid:1; u8 has_atomic_enable_pte_bit:1; u8 has_flat_ccs:1; -- cgit v1.2.3-59-g8ed1b From 71be802005074a4cc2297e4a1da1ca268d9c6b49 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Mon, 3 Feb 2025 17:58:58 -0300 Subject: drm/i915/dmc_wl: Track INITIATE_PM_DMD_REQ for DC5 The Bspec has been updated to include INITIATE_PM_DMD_REQ in the set of register offsets that require the DMC wakelock for access during DC5. Update our table accordingly. Bspec: 71583 Reviewed-by: Luca Coelho Link: https://patchwork.freedesktop.org/patch/msgid/20250203205941.251754-1-gustavo.sousa@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 43884740f8ea..86ba159b683c 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -102,6 +102,7 @@ static const struct intel_dmc_wl_range xe3lpd_dc5_dc6_dmc_ranges[] = { { .start = 0x42088 }, /* CHICKEN_MISC_3 */ { .start = 0x46160 }, /* CMTG_CLK_SEL */ { .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */ + { .start = 0x45230 }, /* INITIATE_PM_DMD_REQ */ {}, }; -- cgit v1.2.3-59-g8ed1b From eaf53ac4901fbb06a94cc0b7842567b3d13c0492 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Wed, 22 Jan 2025 11:03:57 +0530 Subject: drm/display/dp: Define function to setup Extended wake time Extended wake timeout request helps to give additional time by reading the DPCD register through which sink requests the minimal amount of time required to wake the sink up. Source device shall keep retying the AUX tansaction till the extended timeout that is being granted for LTTPRs from the sink device. --v2 -Add documentation [Dmitry] Spec: DP v2.1 Section 3.6.12.3 Signed-off-by: Suraj Kandpal Reviewed-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20250122053358.1545039-3-suraj.kandpal@intel.com --- drivers/gpu/drm/display/drm_dp_helper.c | 58 +++++++++++++++++++++++++++++++++ include/drm/display/drm_dp_helper.h | 1 + 2 files changed, 59 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index da3c8521a7fa..c488d160a3c1 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -459,6 +459,64 @@ void drm_dp_lttpr_link_train_channel_eq_delay(const struct drm_dp_aux *aux, } EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay); +/** + * drm_dp_lttpr_wake_timeout_setup() - Grant extended time for sink to wake up + * @aux: The DP AUX channel to use + * @transparent_mode: This is true if lttpr is in transparent mode + * + * This function checks if the sink needs any extended wake time, if it does + * it grants this request. Post this setup the source device can keep trying + * the Aux transaction till the granted wake timeout. + * If this function is not called all Aux transactions are expected to take + * a default of 1ms before they throw an error. + */ +void drm_dp_lttpr_wake_timeout_setup(struct drm_dp_aux *aux, bool transparent_mode) +{ + u8 val = 1; + int ret; + + if (transparent_mode) { + static const u8 timeout_mapping[] = { + [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_1_MS] = 1, + [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_20_MS] = 20, + [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_40_MS] = 40, + [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_60_MS] = 60, + [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_80_MS] = 80, + [DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_100_MS] = 100, + }; + + ret = drm_dp_dpcd_readb(aux, DP_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_REQUEST, &val); + if (ret != 1) { + drm_dbg_kms(aux->drm_dev, + "Failed to read Extended sleep wake timeout request\n"); + return; + } + + val = (val < sizeof(timeout_mapping) && timeout_mapping[val]) ? + timeout_mapping[val] : 1; + + if (val > 1) + drm_dp_dpcd_writeb(aux, + DP_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_GRANT, + DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_GRANTED); + } else { + ret = drm_dp_dpcd_readb(aux, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &val); + if (ret != 1) { + drm_dbg_kms(aux->drm_dev, + "Failed to read Extended sleep wake timeout request\n"); + return; + } + + val = (val & DP_EXTENDED_WAKE_TIMEOUT_REQUEST_MASK) ? + (val & DP_EXTENDED_WAKE_TIMEOUT_REQUEST_MASK) * 10 : 1; + + if (val > 1) + drm_dp_dpcd_writeb(aux, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, + DP_EXTENDED_WAKE_TIMEOUT_GRANT); + } +} +EXPORT_SYMBOL(drm_dp_lttpr_wake_timeout_setup); + u8 drm_dp_link_rate_to_bw_code(int link_rate) { switch (link_rate) { diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index 8f4054a56039..89a34dff85a4 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -633,6 +633,7 @@ int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]); int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]); bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]); bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]); +void drm_dp_lttpr_wake_timeout_setup(struct drm_dp_aux *aux, bool transparent_mode); void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); -- cgit v1.2.3-59-g8ed1b From 242d9bf59a0a8293acf3e67264875abd0b573614 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Wed, 22 Jan 2025 11:03:58 +0530 Subject: drm/i915/lttpr: Enable Extended Wake Timeout Usually retimers take around 30 to 40ms to exit all devices from sleep state. Extended wake timeout mechanism helps to give that additional time. --v2 -Grant the requested time only if greater than 1ms [Arun/Jani] -Reframe commit message [Arun] --v3 -Move the function to drm_core [Dmitry/Jani] Spec: DP v2.1 Section 3.6.12.3 Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20250122053358.1545039-4-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 ++++ drivers/gpu/drm/i915/display/intel_dp_link_training.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_link_training.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 49b5cc01ce40..a70e7f263a89 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2546,6 +2546,7 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); + bool transparent_mode; intel_dp_set_link_params(intel_dp, crtc_state->port_clock, @@ -2600,6 +2601,9 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, if (!is_mst) intel_dp_set_power(intel_dp, DP_SET_POWER_D0); + transparent_mode = intel_dp_lttpr_transparent_mode_enabled(intel_dp); + drm_dp_lttpr_wake_timeout_setup(&intel_dp->aux, transparent_mode); + intel_dp_configure_protocol_converter(intel_dp, crtc_state); if (!is_mst) intel_dp_sink_enable_decompression(state, diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 397cc4ebae52..c911d4a19e62 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -127,7 +127,7 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable) return true; } -static bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp) +bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp) { return intel_dp->lttpr_common_caps[DP_PHY_REPEATER_MODE - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV] == diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h index 2066b9146762..46614124569f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h @@ -15,6 +15,7 @@ struct intel_dp; int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 dpcd[DP_RECEIVER_CAP_SIZE]); int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp); +bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp); void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate, bool is_vrr); -- cgit v1.2.3-59-g8ed1b From 51d262a96bc6c87f5dababf5136c978afa59f28e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 4 Feb 2025 09:51:59 +0100 Subject: drm/atomic-helper: improve CRTC enabled/connectors mismatch logging message This message reports a mismatch between new_crtc_state->enable and has_connectors, which should be either both true or both false. However it does not mention which one is true and which is false, which can be useful for debugging. Add the value of both avriables to the log message. Reviewed-by: Dmitry Baryshkov Acked-by: Louis Chauvet Signed-off-by: Luca Ceresoli Link: https://patchwork.freedesktop.org/patch/msgid/20250204-drm-small-improvements-v4-2-d6bbc92f12f1@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/drm_atomic_helper.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 3034ba09c0ee..26bf2465cee7 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -690,8 +690,9 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, } if (new_crtc_state->enable != has_connectors) { - drm_dbg_atomic(dev, "[CRTC:%d:%s] enabled/connectors mismatch\n", - crtc->base.id, crtc->name); + drm_dbg_atomic(dev, "[CRTC:%d:%s] enabled/connectors mismatch (%d/%d)\n", + crtc->base.id, crtc->name, + new_crtc_state->enable, has_connectors); return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From 8cca475b8085e551b3eebf4f2164e56c800402e0 Mon Sep 17 00:00:00 2001 From: Paz Zcharya Date: Wed, 29 Jan 2025 14:20:58 +0000 Subject: drm/vkms: Add support for ABGR8888 pixel format Add support for pixel format ABGR8888, which is the default format on Android devices. This will allow us to use VKMS as the default display driver in Android Emulator (Cuttlefish) and increase VKMS adoption. Signed-off-by: Paz Zcharya Reviewed-by: Louis Chauvet Link: https://patchwork.freedesktop.org/patch/msgid/20250129142238.562999-1-pazz@google.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_formats.c | 32 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_plane.c | 1 + drivers/gpu/drm/vkms/vkms_writeback.c | 1 + 3 files changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 39b1d7c97d45..30a64ecca87c 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -253,6 +253,26 @@ static void XRGB8888_read_line(const struct vkms_plane_state *plane, int x_start } } +static void ABGR8888_read_line(const struct vkms_plane_state *plane, int x_start, int y_start, + enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) +{ + struct pixel_argb_u16 *end = out_pixel + count; + u8 *src_pixels; + + packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels); + + int step = get_block_step_bytes(plane->frame_info->fb, direction, 0); + + while (out_pixel < end) { + u8 *px = (u8 *)src_pixels; + /* Switch blue and red pixels. */ + *out_pixel = argb_u16_from_u8888(px[3], px[0], px[1], px[2]); + out_pixel += 1; + src_pixels += step; + } +} + static void ARGB16161616_read_line(const struct vkms_plane_state *plane, int x_start, int y_start, enum pixel_read_direction direction, int count, struct pixel_argb_u16 out_pixel[]) @@ -344,6 +364,14 @@ static void argb_u16_to_XRGB8888(u8 *out_pixel, const struct pixel_argb_u16 *in_ out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257); } +static void argb_u16_to_ABGR8888(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) +{ + out_pixel[3] = DIV_ROUND_CLOSEST(in_pixel->a, 257); + out_pixel[2] = DIV_ROUND_CLOSEST(in_pixel->b, 257); + out_pixel[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257); + out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->r, 257); +} + static void argb_u16_to_ARGB16161616(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) { __le16 *pixel = (__le16 *)out_pixel; @@ -420,6 +448,8 @@ pixel_read_line_t get_pixel_read_line_function(u32 format) return &ARGB8888_read_line; case DRM_FORMAT_XRGB8888: return &XRGB8888_read_line; + case DRM_FORMAT_ABGR8888: + return &ABGR8888_read_line; case DRM_FORMAT_ARGB16161616: return &ARGB16161616_read_line; case DRM_FORMAT_XRGB16161616: @@ -453,6 +483,8 @@ pixel_write_t get_pixel_write_function(u32 format) return &argb_u16_to_ARGB8888; case DRM_FORMAT_XRGB8888: return &argb_u16_to_XRGB8888; + case DRM_FORMAT_ABGR8888: + return &argb_u16_to_ABGR8888; case DRM_FORMAT_ARGB16161616: return &argb_u16_to_ARGB16161616; case DRM_FORMAT_XRGB16161616: diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index e2fce471870f..e34f8c7f83c3 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -15,6 +15,7 @@ static const u32 vkms_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, + DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB16161616, DRM_FORMAT_ARGB16161616, DRM_FORMAT_RGB565 diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index e9b5c74d7c58..fe163271d5b5 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -17,6 +17,7 @@ static const u32 vkms_wb_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, + DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB16161616, DRM_FORMAT_ARGB16161616, DRM_FORMAT_RGB565 -- cgit v1.2.3-59-g8ed1b From 78d5d1e20d1de9422f013338a0f2311448588ba7 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 31 Jan 2025 16:37:13 +0100 Subject: drm/xe/relay: Don't use GFP_KERNEL for new transactions VFs use a relay transaction during the resume/reset flow and use of the GFP_KERNEL flag may conflict with the reclaim: -> #0 (fs_reclaim){+.+.}-{0:0}: [ ] __lock_acquire+0x1874/0x2bc0 [ ] lock_acquire+0xd2/0x310 [ ] fs_reclaim_acquire+0xc5/0x100 [ ] mempool_alloc_noprof+0x5c/0x1b0 [ ] __relay_get_transaction+0xdc/0xa10 [xe] [ ] relay_send_to+0x251/0xe50 [xe] [ ] xe_guc_relay_send_to_pf+0x79/0x3a0 [xe] [ ] xe_gt_sriov_vf_connect+0x90/0x4d0 [xe] [ ] xe_uc_init_hw+0x157/0x3b0 [xe] [ ] do_gt_restart+0x1ae/0x650 [xe] [ ] xe_gt_resume+0xb6/0x120 [xe] [ ] xe_pm_runtime_resume+0x15b/0x370 [xe] [ ] xe_pci_runtime_resume+0x73/0x90 [xe] [ ] pci_pm_runtime_resume+0xa0/0x100 [ ] __rpm_callback+0x4d/0x170 [ ] rpm_callback+0x64/0x70 [ ] rpm_resume+0x594/0x790 [ ] __pm_runtime_resume+0x4e/0x90 [ ] xe_pm_runtime_get_ioctl+0x9c/0x160 [xe] Since we have a preallocated pool of relay transactions, which should cover all our normal relay use cases, we may use the GFP_NOWAIT flag when allocating new outgoing transactions. Signed-off-by: Michal Wajdeczko Tested-by: Marcin Bernatowicz Reviewed-by: Marcin Bernatowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250131153713.808-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc_relay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_relay.c b/drivers/gpu/drm/xe/xe_guc_relay.c index 8f62de026724..e5dc94f3e618 100644 --- a/drivers/gpu/drm/xe/xe_guc_relay.c +++ b/drivers/gpu/drm/xe/xe_guc_relay.c @@ -225,7 +225,7 @@ __relay_get_transaction(struct xe_guc_relay *relay, bool incoming, u32 remote, u * with CTB lock held which is marked as used in the reclaim path. * Btw, that's one of the reason why we use mempool here! */ - txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_KERNEL); + txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_NOWAIT); if (!txn) return ERR_PTR(-ENOMEM); -- cgit v1.2.3-59-g8ed1b From 459777724d306315070d24608fcd89aea85516d6 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 31 Jan 2025 19:25:02 +0100 Subject: drm/xe/vf: Don't try to trigger a full GT reset if VF VFs don't have access to the GDRST(0x941c) register that driver uses to reset a GT. Attempt to trigger a reset using debugfs: $ cat /sys/kernel/debug/dri/0000:00:02.1/gt0/force_reset or due to a hang condition detected by the driver leads to: [ ] xe 0000:00:02.1: [drm] GT0: trying reset from force_reset [xe] [ ] xe 0000:00:02.1: [drm] GT0: reset queued [ ] xe 0000:00:02.1: [drm] GT0: reset started [ ] ------------[ cut here ]------------ [ ] xe 0000:00:02.1: [drm] GT0: VF is trying to write 0x1 to an inaccessible register 0x941c+0x0 [ ] WARNING: CPU: 3 PID: 3069 at drivers/gpu/drm/xe/xe_gt_sriov_vf.c:996 xe_gt_sriov_vf_write32+0xc6/0x580 [xe] [ ] RIP: 0010:xe_gt_sriov_vf_write32+0xc6/0x580 [xe] [ ] Call Trace: [ ] [ ] ? show_regs+0x6c/0x80 [ ] ? __warn+0x93/0x1c0 [ ] ? xe_gt_sriov_vf_write32+0xc6/0x580 [xe] [ ] ? report_bug+0x182/0x1b0 [ ] ? handle_bug+0x6e/0xb0 [ ] ? exc_invalid_op+0x18/0x80 [ ] ? asm_exc_invalid_op+0x1b/0x20 [ ] ? xe_gt_sriov_vf_write32+0xc6/0x580 [xe] [ ] ? xe_gt_sriov_vf_write32+0xc6/0x580 [xe] [ ] ? xe_gt_tlb_invalidation_reset+0xef/0x110 [xe] [ ] ? __mutex_unlock_slowpath+0x41/0x2e0 [ ] xe_mmio_write32+0x64/0x150 [xe] [ ] do_gt_reset+0x2f/0xa0 [xe] [ ] gt_reset_worker+0x14e/0x1e0 [xe] [ ] process_one_work+0x21c/0x740 [ ] worker_thread+0x1db/0x3c0 Fix that by sending H2G VF_RESET(0x5507) action instead. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4078 Signed-off-by: Michal Wajdeczko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20250131182502.852-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt.c | 4 ++++ drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 16 ++++++++++++++++ drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 1 + 3 files changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 01a4a852b8f4..9fb8f1e678dc 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -32,6 +32,7 @@ #include "xe_gt_pagefault.h" #include "xe_gt_printk.h" #include "xe_gt_sriov_pf.h" +#include "xe_gt_sriov_vf.h" #include "xe_gt_sysfs.h" #include "xe_gt_tlb_invalidation.h" #include "xe_gt_topology.h" @@ -679,6 +680,9 @@ static int do_gt_reset(struct xe_gt *gt) { int err; + if (IS_SRIOV_VF(gt_to_xe(gt))) + return xe_gt_sriov_vf_reset(gt); + xe_gsc_wa_14015076503(gt, true); xe_mmio_write32(>->mmio, GDRST, GRDOM_FULL); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index 6671030439fd..4831549da319 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -58,6 +58,22 @@ static int vf_reset_guc_state(struct xe_gt *gt) return err; } +/** + * xe_gt_sriov_vf_reset - Reset GuC VF internal state. + * @gt: the &xe_gt + * + * It requires functional `GuC MMIO based communication`_. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_vf_reset(struct xe_gt *gt) +{ + if (!xe_device_uc_enabled(gt_to_xe(gt))) + return -ENODEV; + + return vf_reset_guc_state(gt); +} + static int guc_action_match_version(struct xe_guc *guc, u32 wanted_branch, u32 wanted_major, u32 wanted_minor, u32 *branch, u32 *major, u32 *minor, u32 *patch) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index 912d20814261..ba6c5d74e326 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -12,6 +12,7 @@ struct drm_printer; struct xe_gt; struct xe_reg; +int xe_gt_sriov_vf_reset(struct xe_gt *gt); int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt); int xe_gt_sriov_vf_query_config(struct xe_gt *gt); int xe_gt_sriov_vf_connect(struct xe_gt *gt); -- cgit v1.2.3-59-g8ed1b From 9c9dc9ba4a00510c624588d9860968b26803a2b8 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 3 Feb 2025 15:48:57 -0800 Subject: drm/xe/pxp: Fail the load if PXP fails to initialize The PXP implementation mimics the i915 approach of allowing the load to continue even if PXP init has failed. On Xe however we're taking an harder stance on boot error and only allowing the load to complete if everything is working, so update the code to fail if anything goes wrong during PXP init. While at it, update the return code in case of PXP not supported to be 0 instead of EOPNOTSUPP, to follow the standard of functions called by xe_device_probe where every non-zero value means failure. Suggested-by: Lucas De Marchi Signed-off-by: Daniele Ceraolo Spurio Cc: Lucas De Marchi Cc: John Harrison Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20250203234857.1419637-1-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_device.c | 4 ++-- drivers/gpu/drm/xe/xe_pxp.c | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index f30f8f668dee..c641c802d4fb 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -864,8 +864,8 @@ int xe_device_probe(struct xe_device *xe) /* A PXP init failure is not fatal */ err = xe_pxp_init(xe); - if (err && err != -EOPNOTSUPP) - drm_err(&xe->drm, "PXP initialization failed: %pe\n", ERR_PTR(err)); + if (err) + goto err_fini_display; err = drm_dev_register(&xe->drm, 0); if (err) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 5e7a1688a771..3cd3f83e86b0 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -372,8 +372,8 @@ static void pxp_fini(void *arg) * are performed asynchronously as part of the GSC init. PXP can only be used * after both this function and the async worker have completed. * - * Returns -EOPNOTSUPP if PXP is not supported, 0 if PXP initialization is - * successful, other errno value if there is an error during the init. + * Returns 0 if PXP is not supported or if PXP initialization is successful, + * other errno value if there is an error during the init. */ int xe_pxp_init(struct xe_device *xe) { @@ -382,26 +382,28 @@ int xe_pxp_init(struct xe_device *xe) int err; if (!xe_pxp_is_supported(xe)) - return -EOPNOTSUPP; + return 0; /* we only support PXP on single tile devices with a media GT */ if (xe->info.tile_count > 1 || !gt) - return -EOPNOTSUPP; + return 0; /* The GSCCS is required for submissions to the GSC FW */ if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0))) - return -EOPNOTSUPP; + return 0; /* PXP requires both GSC and HuC firmwares to be available */ if (!xe_uc_fw_is_loadable(>->uc.gsc.fw) || !xe_uc_fw_is_loadable(>->uc.huc.fw)) { drm_info(&xe->drm, "skipping PXP init due to missing FW dependencies"); - return -EOPNOTSUPP; + return 0; } pxp = drmm_kzalloc(&xe->drm, sizeof(struct xe_pxp), GFP_KERNEL); - if (!pxp) - return -ENOMEM; + if (!pxp) { + err = -ENOMEM; + goto out; + } INIT_LIST_HEAD(&pxp->queues.list); spin_lock_init(&pxp->queues.lock); @@ -448,6 +450,8 @@ out_wq: destroy_workqueue(pxp->irq.wq); out_free: drmm_kfree(&xe->drm, pxp); +out: + drm_err(&xe->drm, "PXP initialization failed: %pe\n", ERR_PTR(err)); return err; } -- cgit v1.2.3-59-g8ed1b From 4a82ceb04ad4bbb9cc20925abccb70938313e555 Mon Sep 17 00:00:00 2001 From: Vinay Belgaumkar Date: Fri, 17 Jan 2025 13:57:53 -0800 Subject: drm/i915/slpc: Add sysfs for SLPC power profiles Default SLPC power profile is Base(0). Power Saving mode(1) has conservative up/down thresholds and is suitable for use with apps that typically need to be power efficient. Selected power profile will be displayed in this format- $ cat slpc_power_profile [base] power_saving $ echo power_saving > slpc_power_profile $ cat slpc_power_profile base [power_saving] v2: Disable waitboost in power saving profile, update sysfs format and add some kernel doc for SLPC (Rodrigo) v3: Update doc with info about power profiles (Rodrigo) v4: Checkpatch warning and remove extra line (Rodrigo) Cc: Sushma Venkatesh Reddy Cc: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar Link: https://patchwork.freedesktop.org/patch/msgid/20250117215753.749906-1-vinay.belgaumkar@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 47 ++++++++++++++++ drivers/gpu/drm/i915/gt/intel_rps.c | 4 ++ .../gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 5 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 65 ++++++++++++++++++++++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 3 + 6 files changed, 125 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c index d7784650e4d9..1154cd2b7c34 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c @@ -464,6 +464,45 @@ static ssize_t slpc_ignore_eff_freq_store(struct kobject *kobj, return err ?: count; } +static ssize_t slpc_power_profile_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buff) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); + struct intel_guc_slpc *slpc = >->uc.guc.slpc; + + switch (slpc->power_profile) { + case SLPC_POWER_PROFILES_BASE: + return sysfs_emit(buff, "[%s] %s\n", "base", "power_saving"); + case SLPC_POWER_PROFILES_POWER_SAVING: + return sysfs_emit(buff, "%s [%s]\n", "base", "power_saving"); + } + + return sysfs_emit(buff, "%u\n", slpc->power_profile); +} + +static ssize_t slpc_power_profile_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buff, size_t count) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); + struct intel_guc_slpc *slpc = >->uc.guc.slpc; + char power_saving[] = "power_saving"; + char base[] = "base"; + int err; + u32 val; + + if (!strncmp(buff, power_saving, sizeof(power_saving) - 1)) + val = SLPC_POWER_PROFILES_POWER_SAVING; + else if (!strncmp(buff, base, sizeof(base) - 1)) + val = SLPC_POWER_PROFILES_BASE; + else + return -EINVAL; + + err = intel_guc_slpc_set_power_profile(slpc, val); + return err ?: count; +} + struct intel_gt_bool_throttle_attr { struct attribute attr; ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, @@ -668,6 +707,7 @@ INTEL_GT_ATTR_RO(media_RP0_freq_mhz); INTEL_GT_ATTR_RO(media_RPn_freq_mhz); INTEL_GT_ATTR_RW(slpc_ignore_eff_freq); +INTEL_GT_ATTR_RW(slpc_power_profile); static const struct attribute *media_perf_power_attrs[] = { &attr_media_freq_factor.attr, @@ -864,6 +904,13 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj) gt_warn(gt, "failed to create ignore_eff_freq sysfs (%pe)", ERR_PTR(ret)); } + if (intel_uc_uses_guc_slpc(>->uc)) { + ret = sysfs_create_file(kobj, &attr_slpc_power_profile.attr); + if (ret) + gt_warn(gt, "failed to create slpc_power_profile sysfs (%pe)", + ERR_PTR(ret)); + } + if (i915_mmio_reg_valid(intel_gt_perf_limit_reasons_reg(gt))) { ret = sysfs_create_files(kobj, throttle_reason_attrs); if (ret) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index c9cb2a391942..1b565ef81d38 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1024,6 +1024,10 @@ void intel_rps_boost(struct i915_request *rq) if (rps_uses_slpc(rps)) { slpc = rps_to_slpc(rps); + /* Waitboost should not be done with power saving profile */ + if (slpc->power_profile == SLPC_POWER_PROFILES_POWER_SAVING) + return; + if (slpc->min_freq_softlimit >= slpc->boost_freq) return; diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h index c34674e797c6..6de87ae5669e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h @@ -228,6 +228,11 @@ struct slpc_optimized_strategies { #define SLPC_OPTIMIZED_STRATEGY_COMPUTE REG_BIT(0) +enum slpc_power_profiles { + SLPC_POWER_PROFILES_BASE = 0x0, + SLPC_POWER_PROFILES_POWER_SAVING = 0x1 +}; + /** * DOC: SLPC H2G MESSAGE FORMAT * diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 706fffca698b..e6e373cb5da8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -15,6 +15,34 @@ #include "gt/intel_gt_regs.h" #include "gt/intel_rps.h" +/** + * DOC: SLPC - Dynamic Frequency management + * + * Single Loop Power Control (SLPC) is a GuC algorithm that manages + * GT frequency based on busyness and how KMD initializes it. SLPC is + * almost completely in control after initialization except for a few + * scenarios mentioned below. + * + * KMD uses the concept of waitboost to ramp frequency to RP0 when there + * are pending submissions for a context. It achieves this by sending GuC a + * request to update the min frequency to RP0. Waitboost is disabled + * when the request retires. + * + * Another form of frequency control happens through per-context hints. + * A context can be marked as low latency during creation. That will ensure + * that SLPC uses an aggressive frequency ramp when that context is active. + * + * Power profiles add another level of control to these mechanisms. + * When power saving profile is chosen, SLPC will use conservative + * thresholds to ramp frequency, thus saving power. KMD will disable + * waitboosts as well, which achieves further power savings. Base profile + * is default and ensures balanced performance for any workload. + * + * Lastly, users have some level of control through sysfs, where min/max + * frequency values can be altered and the use of efficient freq + * can be toggled. + */ + static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc) { return container_of(slpc, struct intel_guc, slpc); @@ -265,6 +293,8 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc) slpc->num_boosts = 0; slpc->media_ratio_mode = SLPC_MEDIA_RATIO_MODE_DYNAMIC_CONTROL; + slpc->power_profile = SLPC_POWER_PROFILES_BASE; + mutex_init(&slpc->lock); INIT_WORK(&slpc->boost_work, slpc_boost_work); @@ -567,6 +597,34 @@ int intel_guc_slpc_set_media_ratio_mode(struct intel_guc_slpc *slpc, u32 val) return ret; } +int intel_guc_slpc_set_power_profile(struct intel_guc_slpc *slpc, u32 val) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + intel_wakeref_t wakeref; + int ret = 0; + + if (val > SLPC_POWER_PROFILES_POWER_SAVING) + return -EINVAL; + + mutex_lock(&slpc->lock); + wakeref = intel_runtime_pm_get(&i915->runtime_pm); + + ret = slpc_set_param(slpc, + SLPC_PARAM_POWER_PROFILE, + val); + if (ret) + guc_err(slpc_to_guc(slpc), + "Failed to set power profile to %d: %pe\n", + val, ERR_PTR(ret)); + else + slpc->power_profile = val; + + intel_runtime_pm_put(&i915->runtime_pm, wakeref); + mutex_unlock(&slpc->lock); + + return ret; +} + void intel_guc_pm_intrmsk_enable(struct intel_gt *gt) { u32 pm_intrmsk_mbz = 0; @@ -728,6 +786,13 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) /* Enable SLPC Optimized Strategy for compute */ intel_guc_slpc_set_strategy(slpc, SLPC_OPTIMIZED_STRATEGY_COMPUTE); + /* Set cached value of power_profile */ + ret = intel_guc_slpc_set_power_profile(slpc, slpc->power_profile); + if (unlikely(ret)) { + guc_probe_error(guc, "Failed to set SLPC power profile: %pe\n", ERR_PTR(ret)); + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h index 1cb5fd44f05c..fc9f761b4372 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h @@ -46,5 +46,6 @@ void intel_guc_slpc_boost(struct intel_guc_slpc *slpc); void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc); int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val); int intel_guc_slpc_set_strategy(struct intel_guc_slpc *slpc, u32 val); +int intel_guc_slpc_set_power_profile(struct intel_guc_slpc *slpc, u32 val); #endif diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h index a88651331497..83673b10ac4e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h @@ -33,6 +33,9 @@ struct intel_guc_slpc { u32 max_freq_softlimit; bool ignore_eff_freq; + /* Base or power saving */ + u32 power_profile; + /* cached media ratio mode */ u32 media_ratio_mode; -- cgit v1.2.3-59-g8ed1b From a5ebe00c2ace15634c02e3c64f1b28253553495b Mon Sep 17 00:00:00 2001 From: Arun R Murthy Date: Wed, 22 Jan 2025 11:25:42 +0530 Subject: drm/i915/dp: Guarantee a minimum HBlank time Mandate a minimum Hblank symbol cycle count between BlankingStart and BlankingEnd in 8b/10b MST and 128b/132b mode. v2: Affine calculation/updation of min HBlank to dp_mst (Jani) v3: moved min_hblank from struct intel_dp to intel_crtc_state (Jani) v4: use max/min functions, change intel_xx *intel_xx to intel_xx *xx (Jani) Limit hblank to 511 and accommodate BS/BE in calculated value (Srikanth) v5: Some spelling corrections (Suraj) v6: Removed DP2.1 in comment as this is applicable for both DP2.1 and DP1.4 (Suraj) v7: crtc_state holds the logical values and the register value computation is moved to mst_enable() (Jani) v8: Limit max hblank to 0x10, disable min_hblank on mst_disable (Jani) Bspec: 74379 Signed-off-by: Arun R Murthy Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/20250122-hblank-v9-1-90afda006685@intel.com --- .../gpu/drm/i915/display/intel_crtc_state_dump.c | 1 + drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 53 +++++++++++++++++++++- drivers/gpu/drm/i915/i915_reg.h | 4 ++ 4 files changed, 58 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 36076e8d639b..ecd0d9853c60 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -249,6 +249,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, str_enabled_disabled(pipe_config->has_sel_update), str_enabled_disabled(pipe_config->has_panel_replay), str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); + drm_printf(&p, "minimum HBlank: %d\n", pipe_config->min_hblank); } drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index cb51b7936f93..f1a9ab4ae85a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1097,6 +1097,7 @@ struct intel_crtc_state { int max_link_bpp_x16; /* in 1/16 bpp units */ int pipe_bpp; /* in 1 bpp units */ + int min_hblank; struct intel_link_m_n dp_m_n; /* m2_n2 for eDP downclock */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 7e58b9464a24..b8f4618d5983 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -209,6 +209,28 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec num_joined_pipes); } +static void intel_dp_mst_compute_min_hblank(struct intel_crtc_state *crtc_state, + struct intel_connector *connector, + int bpp_x16) +{ + struct intel_encoder *encoder = connector->encoder; + struct intel_display *display = to_intel_display(encoder); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int symbol_size = intel_dp_is_uhbr(crtc_state) ? 32 : 8; + int hblank; + + if (DISPLAY_VER(display) < 20) + return; + + /* Calculate min Hblank Link Layer Symbol Cycle Count for 8b/10b MST & 128b/132b */ + hblank = DIV_ROUND_UP((DIV_ROUND_UP + (adjusted_mode->htotal - adjusted_mode->hdisplay, 4) * bpp_x16), + symbol_size); + + crtc_state->min_hblank = hblank; +} + int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, @@ -278,6 +300,9 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state, false, dsc_slice_count, link_bpp_x16); + + intel_dp_mst_compute_min_hblank(crtc_state, connector, link_bpp_x16); + intel_dp_mst_compute_m_n(crtc_state, local_bw_overhead, link_bpp_x16, @@ -967,6 +992,7 @@ static void mst_stream_disable(struct intel_atomic_state *state, struct intel_dp *intel_dp = to_primary_dp(encoder); struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + enum transcoder trans = old_crtc_state->cpu_transcoder; drm_dbg_kms(display->drm, "active links %d\n", intel_dp->active_mst_links); @@ -977,6 +1003,8 @@ static void mst_stream_disable(struct intel_atomic_state *state, intel_hdcp_disable(intel_mst->connector); intel_dp_sink_disable_decompression(state, connector, old_crtc_state); + + intel_de_write(display, DP_MIN_HBLANK_CTL(trans), 0x00); } static void mst_stream_post_disable(struct intel_atomic_state *state, @@ -1249,7 +1277,7 @@ static void mst_stream_enable(struct intel_atomic_state *state, enum transcoder trans = pipe_config->cpu_transcoder; bool first_mst_stream = intel_dp->active_mst_links == 1; struct intel_crtc *pipe_crtc; - int ret, i; + int ret, i, min_hblank; drm_WARN_ON(display->drm, pipe_config->has_pch_encoder); @@ -1264,6 +1292,29 @@ static void mst_stream_enable(struct intel_atomic_state *state, TRANS_DP2_VFREQ_PIXEL_CLOCK(crtc_clock_hz & 0xffffff)); } + if (DISPLAY_VER(display) >= 20) { + /* + * adjust the BlankingStart/BlankingEnd framing control from + * the calculated value + */ + min_hblank = pipe_config->min_hblank - 2; + + /* Maximum value to be programmed is limited to 0x10 */ + min_hblank = min(0x10, min_hblank); + + /* + * Minimum hblank accepted for 128b/132b would be 5 and for + * 8b/10b would be 3 symbol count + */ + if (intel_dp_is_uhbr(pipe_config)) + min_hblank = max(min_hblank, 5); + else + min_hblank = max(min_hblank, 3); + + intel_de_write(display, DP_MIN_HBLANK_CTL(trans), + min_hblank); + } + enable_bs_jitter_was(pipe_config); intel_ddi_enable_transcoder_func(encoder, pipe_config); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 03da51b03fb9..670cd2371f94 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3198,6 +3198,10 @@ #define _TRANS_DP2_VFREQLOW_D 0x630a8 #define TRANS_DP2_VFREQLOW(trans) _MMIO_TRANS(trans, _TRANS_DP2_VFREQLOW_A, _TRANS_DP2_VFREQLOW_B) +#define _DP_MIN_HBLANK_CTL_A 0x600ac +#define _DP_MIN_HBLANK_CTL_B 0x610ac +#define DP_MIN_HBLANK_CTL(trans) _MMIO_TRANS(trans, _DP_MIN_HBLANK_CTL_A, _DP_MIN_HBLANK_CTL_B) + /* SNB eDP training params */ /* SNB A-stepping */ #define EDP_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22) -- cgit v1.2.3-59-g8ed1b From 550b82651bbd4339ac415933bc21e979d439cab4 Mon Sep 17 00:00:00 2001 From: Vignesh Raman Date: Wed, 5 Feb 2025 13:46:46 +0530 Subject: drm/ci: uprev mesa Uprev mesa to adapt to the latest changes in mesa ci which includes new container jobs and stages. Also update lava-submit script to adapt to the recent changes in mesa to use LAVA rootfs overlays. Signed-off-by: Vignesh Raman Signed-off-by: Helen Koike Link: https://patchwork.freedesktop.org/patch/msgid/20250205081652.1928927-2-vignesh.raman@collabora.com --- drivers/gpu/drm/ci/build.sh | 2 +- drivers/gpu/drm/ci/build.yml | 103 +++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/ci/container.yml | 22 ++++---- drivers/gpu/drm/ci/gitlab-ci.yml | 81 +++++++++++++++++++++--------- drivers/gpu/drm/ci/igt_runner.sh | 13 ++--- drivers/gpu/drm/ci/image-tags.yml | 11 +++- drivers/gpu/drm/ci/lava-submit.sh | 100 +++++++++++++++++++++++++----------- drivers/gpu/drm/ci/test.yml | 17 +++---- 8 files changed, 264 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ci/build.sh b/drivers/gpu/drm/ci/build.sh index 139b81db6312..19fe01257ab9 100644 --- a/drivers/gpu/drm/ci/build.sh +++ b/drivers/gpu/drm/ci/build.sh @@ -132,7 +132,7 @@ fi # Pass needed files to the test stage mkdir -p install cp -rfv .gitlab-ci/* install/. -cp -rfv ci/* install/. +cp -rfv bin/ci/* install/. cp -rfv install/common install/ci-common cp -rfv drivers/gpu/drm/ci/* install/. diff --git a/drivers/gpu/drm/ci/build.yml b/drivers/gpu/drm/ci/build.yml index 9c198239033d..a2baa00a20db 100644 --- a/drivers/gpu/drm/ci/build.yml +++ b/drivers/gpu/drm/ci/build.yml @@ -2,7 +2,7 @@ extends: - .build-rules - .container+build-rules - stage: build + stage: build-only artifacts: paths: - artifacts @@ -110,3 +110,104 @@ build-nodebugfs:arm64: build:x86_64: extends: .build:x86_64 + +# Disable build jobs that we won't use +alpine-build-testing: + rules: + - when: never + +debian-android: + rules: + - when: never + +debian-arm32: + rules: + - when: never + +debian-arm32-asan: + rules: + - when: never + +debian-arm64: + rules: + - when: never + +debian-arm64-asan: + rules: + - when: never + +debian-arm64-build-test: + rules: + - when: never + +debian-arm64-release: + rules: + - when: never + +debian-build-testing: + rules: + - when: never + +debian-clang: + rules: + - when: never + +debian-clang-release: + rules: + - when: never + +debian-no-libdrm: + rules: + - when: never + +debian-ppc64el: + rules: + - when: never + +debian-release: + rules: + - when: never + +debian-s390x: + rules: + - when: never + +debian-testing: + rules: + - when: never + +debian-testing-asan: + rules: + - when: never + +debian-testing-msan: + rules: + - when: never + +debian-vulkan: + rules: + - when: never + +debian-x86_32: + rules: + - when: never + +fedora-release: + rules: + - when: never + +rustfmt: + rules: + - when: never + +shader-db: + rules: + - when: never + +windows-msvc: + rules: + - when: never + +yaml-toml-shell-py-test: + rules: + - when: never diff --git a/drivers/gpu/drm/ci/container.yml b/drivers/gpu/drm/ci/container.yml index 2a94f54ce4cf..07dc13ff865d 100644 --- a/drivers/gpu/drm/ci/container.yml +++ b/drivers/gpu/drm/ci/container.yml @@ -24,7 +24,7 @@ alpine/x86_64_build: rules: - when: never -debian/x86_64_test-vk: +debian/arm64_test-gl: rules: - when: never @@ -32,7 +32,15 @@ debian/arm64_test-vk: rules: - when: never -debian/arm64_test-gl: +debian/ppc64el_build: + rules: + - when: never + +debian/s390x_build: + rules: + - when: never + +debian/x86_64_test-vk: rules: - when: never @@ -56,14 +64,6 @@ windows_test_msvc: rules: - when: never -.debian/x86_64_build-mingw: - rules: - - when: never - -rustfmt: - rules: - - when: never - windows_msvc: rules: - - when: never \ No newline at end of file + - when: never diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml index b7214718723c..48ab2de9c90b 100644 --- a/drivers/gpu/drm/ci/gitlab-ci.yml +++ b/drivers/gpu/drm/ci/gitlab-ci.yml @@ -1,6 +1,6 @@ variables: DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa - DRM_CI_COMMIT_SHA: &drm-ci-commit-sha c6a9a9c3bce90923f7700219354e0b6e5a3c9ba6 + DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 7d3062470f3ccc6cb40540e772e902c7e2248024 UPSTREAM_REPO: https://gitlab.freedesktop.org/drm/kernel.git TARGET_BRANCH: drm-next @@ -20,6 +20,9 @@ variables: rm download-git-cache.sh set +o xtrace S3_JWT_FILE: /s3_jwt + S3_JWT_FILE_SCRIPT: |- + echo -n '${S3_JWT}' > '${S3_JWT_FILE}' && + unset CI_JOB_JWT S3_JWT # Unsetting vulnerable env variables S3_HOST: s3.freedesktop.org # This bucket is used to fetch the kernel image S3_KERNEL_BUCKET: mesa-rootfs @@ -31,11 +34,7 @@ variables: PIPELINE_ARTIFACTS_BASE: ${S3_HOST}/${S3_ARTIFACTS_BUCKET}/${CI_PROJECT_PATH}/${CI_PIPELINE_ID} # per-job artifact storage on MinIO JOB_ARTIFACTS_BASE: ${PIPELINE_ARTIFACTS_BASE}/${CI_JOB_ID} - # default kernel for rootfs before injecting the current kernel tree - KERNEL_REPO: "gfx-ci/linux" - KERNEL_TAG: "v6.6.21-mesa-f8ea" KERNEL_IMAGE_BASE: https://${S3_HOST}/${S3_KERNEL_BUCKET}/${KERNEL_REPO}/${KERNEL_TAG} - PKG_REPO_REV: "3cc12a2a" LAVA_TAGS: subset-1-gfx LAVA_JOB_PRIORITY: 30 ARTIFACTS_BASE_URL: https://${CI_PROJECT_ROOT_NAMESPACE}.${CI_PAGES_DOMAIN}/-/${CI_PROJECT_NAME}/-/jobs/${CI_JOB_ID}/artifacts @@ -50,16 +49,13 @@ default: - export SCRIPTS_DIR=$(mktemp -d) - curl -L -s --retry 4 -f --retry-all-errors --retry-delay 60 -O --output-dir "${SCRIPTS_DIR}" "${DRM_CI_PROJECT_URL}/-/raw/${DRM_CI_COMMIT_SHA}/.gitlab-ci/setup-test-env.sh" - source ${SCRIPTS_DIR}/setup-test-env.sh - - echo -e "\e[0Ksection_start:$(date +%s):unset_env_vars_section[collapsed=true]\r\e[0KUnsetting vulnerable environment variables" - - echo -n "${S3_JWT}" > "${S3_JWT_FILE}" - - unset CI_JOB_JWT S3_JWT - - echo -e "\e[0Ksection_end:$(date +%s):unset_env_vars_section\r\e[0K" + - eval "$S3_JWT_FILE_SCRIPT" - echo -e "\e[0Ksection_start:$(date +%s):drm_ci_download_section[collapsed=true]\r\e[0KDownloading mesa from $DRM_CI_PROJECT_URL/-/archive/$DRM_CI_COMMIT_SHA/mesa-$DRM_CI_COMMIT_SHA.tar.gz" - cd $CI_PROJECT_DIR - curl --output - $DRM_CI_PROJECT_URL/-/archive/$DRM_CI_COMMIT_SHA/mesa-$DRM_CI_COMMIT_SHA.tar.gz | tar -xz - mv mesa-$DRM_CI_COMMIT_SHA/.gitlab-ci* . - - mv mesa-$DRM_CI_COMMIT_SHA/bin/ci . + - mv mesa-$DRM_CI_COMMIT_SHA/bin . - rm -rf mesa-$DRM_CI_COMMIT_SHA/ - echo -e "\e[0Ksection_end:$(date +%s):drm_ci_download_section\r\e[0K" @@ -85,6 +81,7 @@ include: - project: *drm-ci-project-path ref: *drm-ci-commit-sha file: + - '/.gitlab-ci/build/gitlab-ci.yml' - '/.gitlab-ci/container/gitlab-ci.yml' - '/.gitlab-ci/farm-rules.yml' - '/.gitlab-ci/lava/lava-gitlab-ci.yml' @@ -115,9 +112,10 @@ include: stages: - sanity - container - - code-validation - git-archive - - build + - build-for-tests + - build-only + - code-validation - amdgpu - i915 - mediatek @@ -197,7 +195,7 @@ stages: .ci-deqp-artifacts: artifacts: - name: "mesa_${CI_JOB_NAME}" + name: "${CI_PROJECT_NAME}_${CI_JOB_NAME}" when: always untracked: false paths: @@ -264,30 +262,63 @@ sanity: rules: - if: *is-pre-merge when: on_success - # Other cases default to never + - when: never variables: GIT_STRATEGY: none script: # ci-fairy check-commits --junit-xml=check-commits.xml - ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request.xml + - | + set -eu + image_tags=( + ALPINE_X86_64_LAVA_SSH_TAG + CONTAINER_TAG + DEBIAN_BASE_TAG + DEBIAN_BUILD_TAG + DEBIAN_PYUTILS_TAG + DEBIAN_TEST_GL_TAG + KERNEL_ROOTFS_TAG + KERNEL_TAG + PKG_REPO_REV + ) + for var in "${image_tags[@]}" + do + if [ "$(echo -n "${!var}" | wc -c)" -gt 20 ] + then + echo "$var is too long; please make sure it is at most 20 chars." + exit 1 + fi + done artifacts: when: on_failure reports: junit: check-*.xml + tags: + - placeholder-job -# Rules for tests that should not block merging, but should be available to -# optionally run with the "play" button in the UI in pre-merge non-marge -# pipelines. This should appear in "extends:" after any includes of -# test-source-dep.yml rules, so that these rules replace those. -.test-manual-mr: + +mr-label-maker-test: + extends: + - .fdo.ci-fairy + stage: sanity rules: - - !reference [.no_scheduled_pipelines-rules, rules] - - if: *is-forked-branch-or-pre-merge-not-for-marge - when: manual + - !reference [.mr-label-maker-rules, rules] variables: - JOB_TIMEOUT: 80 - + GIT_STRATEGY: fetch + timeout: 10m + script: + - set -eu + - python3 -m venv .venv + - source .venv/bin/activate + - pip install git+https://gitlab.freedesktop.org/freedesktop/mr-label-maker + - mr-label-maker --dry-run --mr $CI_MERGE_REQUEST_IID # Jobs that need to pass before spending hardware resources on further testing .required-for-hardware-jobs: - needs: [] + needs: + - job: clang-format + optional: true + - job: rustfmt + optional: true + - job: toml-lint + optional: true diff --git a/drivers/gpu/drm/ci/igt_runner.sh b/drivers/gpu/drm/ci/igt_runner.sh index f38836ec837c..68b042e43b7f 100755 --- a/drivers/gpu/drm/ci/igt_runner.sh +++ b/drivers/gpu/drm/ci/igt_runner.sh @@ -47,7 +47,7 @@ else ARCH="x86_64" fi -curl -L --retry 4 -f --retry-all-errors --retry-delay 60 -s ${FDO_HTTP_CACHE_URI:-}$PIPELINE_ARTIFACTS_BASE/$ARCH/igt.tar.gz | tar --zstd -v -x -C / +curl -L --retry 4 -f --retry-all-errors --retry-delay 60 -s $PIPELINE_ARTIFACTS_BASE/$ARCH/igt.tar.gz | tar --zstd -v -x -C / TESTLIST="/igt/libexec/igt-gpu-tools/ci-testlist.txt" @@ -69,7 +69,7 @@ igt-runner \ run \ --igt-folder /igt/libexec/igt-gpu-tools \ --caselist $TESTLIST \ - --output /results \ + --output $RESULTS_DIR \ -vvvv \ $IGT_SKIPS \ $IGT_FLAKES \ @@ -80,13 +80,10 @@ set -e deqp-runner junit \ --testsuite IGT \ - --results /results/failures.csv \ - --output /results/junit.xml \ + --results $RESULTS_DIR/failures.csv \ + --output $RESULTS_DIR/junit.xml \ --limit 50 \ - --template "See https://$CI_PROJECT_ROOT_NAMESPACE.pages.freedesktop.org/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/results/{{testcase}}.xml" - -# Store the results also in the simpler format used by the runner in ChromeOS CI -#sed -r 's/(dmesg-warn|pass)/success/g' /results/results.txt > /results/results_simple.txt + --template "See $ARTIFACTS_BASE_URL/results/{{testcase}}.xml" cd $oldpath exit $ret diff --git a/drivers/gpu/drm/ci/image-tags.yml b/drivers/gpu/drm/ci/image-tags.yml index 8d8b9e71852e..20049f3626b2 100644 --- a/drivers/gpu/drm/ci/image-tags.yml +++ b/drivers/gpu/drm/ci/image-tags.yml @@ -1,5 +1,5 @@ variables: - CONTAINER_TAG: "2024-09-09-uprevs" + CONTAINER_TAG: "20250204-mesa-uprev" DEBIAN_X86_64_BUILD_BASE_IMAGE: "debian/x86_64_build-base" DEBIAN_BASE_TAG: "${CONTAINER_TAG}" @@ -7,9 +7,16 @@ variables: DEBIAN_BUILD_TAG: "${CONTAINER_TAG}" KERNEL_ROOTFS_TAG: "${CONTAINER_TAG}" + # default kernel for rootfs before injecting the current kernel tree + KERNEL_TAG: "v6.13-rc4-mesa-5e77" + KERNEL_REPO: "gfx-ci/linux" + PKG_REPO_REV: "bca9635d" DEBIAN_X86_64_TEST_BASE_IMAGE: "debian/x86_64_test-base" DEBIAN_X86_64_TEST_IMAGE_GL_PATH: "debian/x86_64_test-gl" DEBIAN_TEST_GL_TAG: "${CONTAINER_TAG}" - ALPINE_X86_64_LAVA_SSH_TAG: "${CONTAINER_TAG}" \ No newline at end of file + DEBIAN_PYUTILS_IMAGE: "debian/x86_64_pyutils" + DEBIAN_PYUTILS_TAG: "${CONTAINER_TAG}" + + ALPINE_X86_64_LAVA_SSH_TAG: "${CONTAINER_TAG}" diff --git a/drivers/gpu/drm/ci/lava-submit.sh b/drivers/gpu/drm/ci/lava-submit.sh index 6add15083c78..6e5ac51e8c0a 100755 --- a/drivers/gpu/drm/ci/lava-submit.sh +++ b/drivers/gpu/drm/ci/lava-submit.sh @@ -1,58 +1,102 @@ -#!/bin/bash +#!/usr/bin/env bash # SPDX-License-Identifier: MIT +# shellcheck disable=SC2086 # we want word splitting +# shellcheck disable=SC1091 # paths only become valid at runtime -set -e -set -x +# If we run in the fork (not from mesa or Marge-bot), reuse mainline kernel and rootfs, if exist. +_check_artifact_path() { + _url="https://${1}/${2}" + if curl -s -o /dev/null -I -L -f --retry 4 --retry-delay 15 "${_url}"; then + echo -n "${_url}" + fi +} -# Try to use the kernel and rootfs built in mainline first, so we're more -# likely to hit cache -if curl -L --retry 4 -f --retry-all-errors --retry-delay 60 -s "https://${BASE_SYSTEM_MAINLINE_HOST_PATH}/done"; then - BASE_SYSTEM_HOST_PATH="${BASE_SYSTEM_MAINLINE_HOST_PATH}" -else - BASE_SYSTEM_HOST_PATH="${BASE_SYSTEM_FORK_HOST_PATH}" -fi +get_path_to_artifact() { + _mainline_artifact="$(_check_artifact_path ${BASE_SYSTEM_MAINLINE_HOST_PATH} ${1})" + if [ -n "${_mainline_artifact}" ]; then + echo -n "${_mainline_artifact}" + return + fi + _fork_artifact="$(_check_artifact_path ${BASE_SYSTEM_FORK_HOST_PATH} ${1})" + if [ -n "${_fork_artifact}" ]; then + echo -n "${_fork_artifact}" + return + fi + set +x + error "Sorry, I couldn't find a viable built path for ${1} in either mainline or a fork." >&2 + echo "" >&2 + echo "If you're working on CI, this probably means that you're missing a dependency:" >&2 + echo "this job ran ahead of the job which was supposed to upload that artifact." >&2 + echo "" >&2 + echo "If you aren't working on CI, please ping @mesa/ci-helpers to see if we can help." >&2 + echo "" >&2 + echo "This job is going to fail, because I can't find the resources I need. Sorry." >&2 + set -x + exit 1 +} + +. "${SCRIPTS_DIR}/setup-test-env.sh" + +section_start prepare_rootfs "Preparing root filesystem" + +set -ex + +section_switch rootfs "Assembling root filesystem" +ROOTFS_URL="$(get_path_to_artifact lava-rootfs.tar.zst)" +[ $? != 1 ] || exit 1 rm -rf results mkdir -p results/job-rootfs-overlay/ -cp artifacts/ci-common/capture-devcoredump.sh results/job-rootfs-overlay/ +artifacts/ci-common/generate-env.sh > results/job-rootfs-overlay/set-job-env-vars.sh cp artifacts/ci-common/init-*.sh results/job-rootfs-overlay/ -cp artifacts/ci-common/intel-gpu-freq.sh results/job-rootfs-overlay/ cp "$SCRIPTS_DIR"/setup-test-env.sh results/job-rootfs-overlay/ -# Prepare env vars for upload. -section_start variables "Variables passed through:" -KERNEL_IMAGE_BASE="https://${BASE_SYSTEM_HOST_PATH}" \ - artifacts/ci-common/generate-env.sh | tee results/job-rootfs-overlay/set-job-env-vars.sh -section_end variables - tar zcf job-rootfs-overlay.tar.gz -C results/job-rootfs-overlay/ . ci-fairy s3cp --token-file "${S3_JWT_FILE}" job-rootfs-overlay.tar.gz "https://${JOB_ROOTFS_OVERLAY_PATH}" +# Prepare env vars for upload. +section_switch variables "Environment variables passed through to device:" +cat results/job-rootfs-overlay/set-job-env-vars.sh + +section_switch lava_submit "Submitting job for scheduling" + touch results/lava.log tail -f results/lava.log & - PYTHONPATH=artifacts/ artifacts/lava/lava_job_submitter.py \ - submit \ + --farm "${FARM}" \ + --device-type "${DEVICE_TYPE}" \ + --boot-method "${BOOT_METHOD}" \ + --job-timeout-min $((CI_JOB_TIMEOUT/60 - 5)) \ --dump-yaml \ --pipeline-info "$CI_JOB_NAME: $CI_PIPELINE_URL on $CI_COMMIT_REF_NAME ${CI_NODE_INDEX}/${CI_NODE_TOTAL}" \ - --rootfs-url-prefix "https://${BASE_SYSTEM_HOST_PATH}" \ + --rootfs-url "${ROOTFS_URL}" \ --kernel-url-prefix "https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}" \ - --build-url "${FDO_HTTP_CACHE_URI:-}https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/kernel-files.tar.zst" \ - --job-rootfs-overlay-url "${FDO_HTTP_CACHE_URI:-}https://${JOB_ROOTFS_OVERLAY_PATH}" \ - --job-timeout-min ${JOB_TIMEOUT:-80} \ + --kernel-external "${EXTERNAL_KERNEL_TAG}" \ --first-stage-init artifacts/ci-common/init-stage1.sh \ - --ci-project-dir "${CI_PROJECT_DIR}" \ - --device-type "${DEVICE_TYPE}" \ - --farm "${FARM}" \ --dtb-filename "${DTB}" \ --jwt-file "${S3_JWT_FILE}" \ --kernel-image-name "${KERNEL_IMAGE_NAME}" \ --kernel-image-type "${KERNEL_IMAGE_TYPE}" \ - --boot-method "${BOOT_METHOD}" \ --visibility-group "${VISIBILITY_GROUP}" \ --lava-tags "${LAVA_TAGS}" \ --mesa-job-name "$CI_JOB_NAME" \ --structured-log-file "results/lava_job_detail.json" \ --ssh-client-image "${LAVA_SSH_CLIENT_IMAGE}" \ + --project-name "${CI_PROJECT_NAME}" \ + --starting-section "${CURRENT_SECTION}" \ + --job-submitted-at "${CI_JOB_STARTED_AT}" \ + - append-overlay \ + --name=kernel-build \ + --url="${FDO_HTTP_CACHE_URI:-}https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/kernel-files.tar.zst" \ + --compression=zstd \ + --path="${CI_PROJECT_DIR}" \ + --format=tar \ + - append-overlay \ + --name=job-overlay \ + --url="https://${JOB_ROOTFS_OVERLAY_PATH}" \ + --compression=gz \ + --path="/" \ + --format=tar \ + - submit \ >> results/lava.log diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml index f0ef60c8f56d..c5c786bf419b 100644 --- a/drivers/gpu/drm/ci/test.yml +++ b/drivers/gpu/drm/ci/test.yml @@ -1,21 +1,21 @@ .test-rules: rules: - - if: '$FD_FARM == "offline" && $RUNNER_TAG =~ /^google-freedreno-/' - when: never - - if: '$COLLABORA_FARM == "offline" && $RUNNER_TAG =~ /^mesa-ci-x86-64-lava-/' - when: never - !reference [.no_scheduled_pipelines-rules, rules] + - !reference [.collabora-farm-rules, rules] + - !reference [.google-freedreno-farm-rules, rules] - when: on_success .lava-test: extends: - .test-rules + - .build-rules + - .container+build-rules timeout: "1h30m" script: # Note: Build dir (and thus install) may be dirty due to GIT_STRATEGY - rm -rf install - tar -xf artifacts/install.tar - - mv install/* artifacts/. + - mv -n install/* artifacts/. # Override it with our lava-submit.sh script - ./artifacts/lava-submit.sh @@ -32,6 +32,7 @@ - alpine/x86_64_lava_ssh_client - kernel+rootfs_arm32 - debian/x86_64_build + - python-artifacts - testing:arm32 - igt:arm32 @@ -48,6 +49,7 @@ - alpine/x86_64_lava_ssh_client - kernel+rootfs_arm64 - debian/x86_64_build + - python-artifacts - testing:arm64 - igt:arm64 @@ -64,6 +66,7 @@ - alpine/x86_64_lava_ssh_client - kernel+rootfs_x86_64 - debian/x86_64_build + - python-artifacts - testing:x86_64 - igt:x86_64 @@ -453,8 +456,6 @@ virtio_gpu:none: script: - ln -sf $CI_PROJECT_DIR/install /install - mv install/bzImage /lava-files/bzImage - - mkdir -p $CI_PROJECT_DIR/results - - ln -sf $CI_PROJECT_DIR/results /results - install/crosvm-runner.sh install/igt_runner.sh needs: - debian/x86_64_test-gl @@ -476,8 +477,6 @@ vkms:none: - ln -sf $CI_PROJECT_DIR/install /install - mv install/bzImage /lava-files/bzImage - mkdir -p /lib/modules - - mkdir -p $CI_PROJECT_DIR/results - - ln -sf $CI_PROJECT_DIR/results /results - ./install/crosvm-runner.sh ./install/igt_runner.sh needs: - debian/x86_64_test-gl -- cgit v1.2.3-59-g8ed1b From df54f04f2020dd750d7c2d6c336ef91375d0db02 Mon Sep 17 00:00:00 2001 From: Vignesh Raman Date: Wed, 5 Feb 2025 13:46:47 +0530 Subject: drm/ci: update gitlab rules Update gitlab rules to include scheduled pipelines. Signed-off-by: Vignesh Raman Signed-off-by: Helen Koike Link: https://patchwork.freedesktop.org/patch/msgid/20250205081652.1928927-3-vignesh.raman@collabora.com --- drivers/gpu/drm/ci/build.yml | 1 - drivers/gpu/drm/ci/gitlab-ci.yml | 116 +++++++++++++++++---------------------- drivers/gpu/drm/ci/test.yml | 26 +++++---- 3 files changed, 63 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ci/build.yml b/drivers/gpu/drm/ci/build.yml index a2baa00a20db..274f118533a7 100644 --- a/drivers/gpu/drm/ci/build.yml +++ b/drivers/gpu/drm/ci/build.yml @@ -1,6 +1,5 @@ .build: extends: - - .build-rules - .container+build-rules stage: build-only artifacts: diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml index 48ab2de9c90b..f04aabe8327c 100644 --- a/drivers/gpu/drm/ci/gitlab-ci.yml +++ b/drivers/gpu/drm/ci/gitlab-ci.yml @@ -41,6 +41,7 @@ variables: # Python scripts for structured logger PYTHONPATH: "$PYTHONPATH:$CI_PROJECT_DIR/install" + default: id_tokens: S3_JWT: @@ -67,6 +68,7 @@ default: export S3_JWT="$(<${S3_JWT_FILE})" && rm "${S3_JWT_FILE}" + include: - project: 'freedesktop/ci-templates' ref: 16bc29078de5e0a067ff84a1a199a3760d3b3811 @@ -126,33 +128,27 @@ stages: - rockchip - software-driver + # YAML anchors for rule conditions # -------------------------------- .rules-anchors: rules: - # Pipeline for forked project branch - - if: &is-forked-branch '$CI_COMMIT_BRANCH && $CI_PROJECT_NAMESPACE != "mesa"' - when: manual - # Forked project branch / pre-merge pipeline not for Marge bot - - if: &is-forked-branch-or-pre-merge-not-for-marge '$CI_PROJECT_NAMESPACE != "mesa" || ($GITLAB_USER_LOGIN != "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event")' - when: manual - # Pipeline runs for the main branch of the upstream Mesa project - - if: &is-mesa-main '$CI_PROJECT_NAMESPACE == "mesa" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_COMMIT_BRANCH' - when: always - # Post-merge pipeline - - if: &is-post-merge '$CI_PROJECT_NAMESPACE == "mesa" && $CI_COMMIT_BRANCH' - when: on_success - # Post-merge pipeline, not for Marge Bot - - if: &is-post-merge-not-for-marge '$CI_PROJECT_NAMESPACE == "mesa" && $GITLAB_USER_LOGIN != "marge-bot" && $CI_COMMIT_BRANCH' - when: on_success + # do not duplicate pipelines on merge pipelines + - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push" + when: never + # merge pipeline + - if: &is-merge-attempt $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event" + # post-merge pipeline + - if: &is-post-merge $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "push" # Pre-merge pipeline - - if: &is-pre-merge '$CI_PIPELINE_SOURCE == "merge_request_event"' - when: on_success - # Pre-merge pipeline for Marge Bot - - if: &is-pre-merge-for-marge '$GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event"' - when: on_success + - if: &is-pre-merge $CI_PIPELINE_SOURCE == "merge_request_event" # Push to a branch on a fork - - &is-fork-push '$CI_PROJECT_NAMESPACE != "mesa" && $CI_PIPELINE_SOURCE == "push"' + - if: &is-fork-push $CI_PROJECT_NAMESPACE != "mesa" && $CI_PIPELINE_SOURCE == "push" + # nightly pipeline + - if: &is-scheduled-pipeline $CI_PIPELINE_SOURCE == "schedule" + # pipeline for direct pushes that bypassed the CI + - if: &is-direct-push $CI_PROJECT_NAMESPACE == "mesa" && $CI_PIPELINE_SOURCE == "push" && $GITLAB_USER_LOGIN != "marge-bot" + # Rules applied to every job in the pipeline .common-rules: @@ -160,39 +156,48 @@ stages: - if: *is-fork-push when: manual + .never-post-merge-rules: rules: - if: *is-post-merge when: never -# Rule to filter for only scheduled pipelines. -.scheduled_pipeline-rules: - rules: - - if: &is-scheduled-pipeline '$CI_PIPELINE_SOURCE == "schedule"' - when: on_success - -# Generic rule to not run the job during scheduled pipelines. Jobs that aren't -# something like a nightly run should include this rule. -.no_scheduled_pipelines-rules: - rules: - - if: *is-scheduled-pipeline - when: never -# When to automatically run the CI for build jobs -.build-rules: - rules: - - !reference [.no_scheduled_pipelines-rules, rules] - - !reference [.never-post-merge-rules, rules] - # Run automatically once all dependency jobs have passed - - when: on_success - -# When to automatically run the CI for container jobs .container+build-rules: rules: - - !reference [.no_scheduled_pipelines-rules, rules] + - !reference [.common-rules, rules] + # Run when re-enabling a disabled farm, but not when disabling it + - !reference [.disable-farm-mr-rules, rules] + # Never run immediately after merging, as we just ran everything - !reference [.never-post-merge-rules, rules] + # Build everything in merge pipelines, if any files affecting the pipeline + # were changed + - if: *is-merge-attempt + changes: &all_paths + - drivers/gpu/drm/ci/**/* + when: on_success + # Same as above, but for pre-merge pipelines + - if: *is-pre-merge + changes: + *all_paths + when: manual + # Skip everything for pre-merge and merge pipelines which don't change + # anything in the build + - if: *is-merge-attempt + when: never + - if: *is-pre-merge + when: never + # Build everything after someone bypassed the CI + - if: *is-direct-push + when: on_success + # Build everything in scheduled pipelines + - if: *is-scheduled-pipeline + when: on_success + # Allow building everything in fork pipelines, but build nothing unless + # manually triggered - when: manual + .ci-deqp-artifacts: artifacts: name: "${CI_PROJECT_NAME}_${CI_JOB_NAME}" @@ -206,31 +211,7 @@ stages: - _build/meson-logs/strace -.container-rules: - rules: - - !reference [.no_scheduled_pipelines-rules, rules] - - !reference [.never-post-merge-rules, rules] - # Run pipeline by default in the main project if any CI pipeline - # configuration files were changed, to ensure docker images are up to date - - if: *is-post-merge - changes: - - drivers/gpu/drm/ci/**/* - when: on_success - # Run pipeline by default if it was triggered by Marge Bot, is for a - # merge request, and any files affecting the pipeline were changed - - if: *is-pre-merge-for-marge - when: on_success - # Run pipeline by default in the main project if it was not triggered by - # Marge Bot, and any files affecting the pipeline were changed - - if: *is-post-merge-not-for-marge - when: on_success - # Allow triggering jobs manually in other cases - - when: manual - - - # Git archive - make git archive: extends: - .fdo.ci-fairy @@ -313,6 +294,7 @@ mr-label-maker-test: - pip install git+https://gitlab.freedesktop.org/freedesktop/mr-label-maker - mr-label-maker --dry-run --mr $CI_MERGE_REQUEST_IID + # Jobs that need to pass before spending hardware resources on further testing .required-for-hardware-jobs: needs: diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml index c5c786bf419b..6a1e059858e5 100644 --- a/drivers/gpu/drm/ci/test.yml +++ b/drivers/gpu/drm/ci/test.yml @@ -1,16 +1,11 @@ -.test-rules: - rules: - - !reference [.no_scheduled_pipelines-rules, rules] - - !reference [.collabora-farm-rules, rules] - - !reference [.google-freedreno-farm-rules, rules] - - when: on_success - .lava-test: extends: - - .test-rules - - .build-rules - .container+build-rules timeout: "1h30m" + rules: + - !reference [.scheduled_pipeline-rules, rules] + - !reference [.collabora-farm-rules, rules] + - when: on_success script: # Note: Build dir (and thus install) may be dirty due to GIT_STRATEGY - rm -rf install @@ -74,8 +69,11 @@ extends: - .baremetal-test-arm64 - .use-debian/baremetal_arm64_test - - .test-rules timeout: "1h30m" + rules: + - !reference [.scheduled_pipeline-rules, rules] + - !reference [.google-freedreno-farm-rules, rules] + - when: on_success variables: FDO_CI_CONCURRENT: 10 HWCI_TEST_SCRIPT: "/install/igt_runner.sh" @@ -444,13 +442,15 @@ panfrost:g12b: virtio_gpu:none: stage: software-driver timeout: "1h30m" + rules: + - !reference [.scheduled_pipeline-rules, rules] + - when: on_success variables: CROSVM_GALLIUM_DRIVER: llvmpipe DRIVER_NAME: virtio_gpu GPU_VERSION: none extends: - .test-gl - - .test-rules tags: - kvm script: @@ -465,12 +465,14 @@ virtio_gpu:none: vkms:none: stage: software-driver timeout: "1h30m" + rules: + - !reference [.scheduled_pipeline-rules, rules] + - when: on_success variables: DRIVER_NAME: vkms GPU_VERSION: none extends: - .test-gl - - .test-rules tags: - kvm script: -- cgit v1.2.3-59-g8ed1b From c5d82ed17eeaad79460e402da7ae58a9e37d8f94 Mon Sep 17 00:00:00 2001 From: Vignesh Raman Date: Wed, 5 Feb 2025 13:46:48 +0530 Subject: drm/ci: update expectation files Update expectation files for the mesa uprev. Signed-off-by: Vignesh Raman Signed-off-by: Helen Koike Link: https://patchwork.freedesktop.org/patch/msgid/20250205081652.1928927-4-vignesh.raman@collabora.com --- drivers/gpu/drm/ci/xfails/vkms-none-fails.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt index 85647eca4e55..6ebcc7d89fbd 100644 --- a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt +++ b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt @@ -13,6 +13,8 @@ kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail kms_cursor_legacy@flip-vs-cursor-legacy,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail +kms_flip@flip-vs-suspend,Fail +kms_flip@flip-vs-suspend-interruptible,Fail kms_lease@lease-uevent,Fail kms_writeback@writeback-check-output,Fail kms_writeback@writeback-check-output-XRGB2101010,Fail -- cgit v1.2.3-59-g8ed1b From b5ee4c2852d381a8f5351231561aa2faed474fe4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 17:37:17 +0200 Subject: drm/i915/mst: fix INT_MAX to .4 fixed point conversion mistake intel_dp_mtp_tu_compute_config() conversion to use .4 fixed point didn't take into account that intel_dp_mst_max_dpt_bpp() may return INT_MAX when the transport limitation is not relevant. Converting INT_MAX to .4 fixed point results in -1.0, which then gets used as if it were a real max BPP value: i915 0000:00:02.0: [drm:intel_dp_mtp_tu_compute_config [i915]] Limiting bpp to max DPT bpp (24.0000 -> -1.0000) i915 0000:00:02.0: [drm:intel_dp_mtp_tu_compute_config [i915]] Looking for slots in range min bpp 18.0000 max bpp -1.0000 Just return 0 for "no max DPT BPP", and handle it explicitly. Fixes: 67782bf6e8a6 ("drm/i915/mst: Convert intel_dp_mtp_tu_compute_config() to .4 format") Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13624 Cc: Imre Deak Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250204153717.2996923-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index b8f4618d5983..ff3ae5db4b54 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -111,7 +111,7 @@ static int intel_dp_mst_max_dpt_bpp(const struct intel_crtc_state *crtc_state, &crtc_state->hw.adjusted_mode; if (!intel_dp_is_uhbr(crtc_state) || DISPLAY_VER(display) >= 20 || !dsc) - return INT_MAX; + return 0; /* * DSC->DPT interface width: @@ -270,7 +270,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, } max_dpt_bpp_x16 = fxp_q4_from_int(intel_dp_mst_max_dpt_bpp(crtc_state, dsc)); - if (max_bpp_x16 > max_dpt_bpp_x16) { + if (max_dpt_bpp_x16 && max_bpp_x16 > max_dpt_bpp_x16) { drm_dbg_kms(display->drm, "Limiting bpp to max DPT bpp (" FXP_Q4_FMT " -> " FXP_Q4_FMT ")\n", FXP_Q4_ARGS(max_bpp_x16), FXP_Q4_ARGS(max_dpt_bpp_x16)); max_bpp_x16 = max_dpt_bpp_x16; -- cgit v1.2.3-59-g8ed1b From a40e718d34d3d02c781c295466b013415f68c4f1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 17:49:25 +0200 Subject: drm/i915/dp: Fix potential infinite loop in 128b/132b SST Passing 0 as the step only works when there are other reasons to break out of the BPP loop in intel_dp_mtp_tu_compute_config(). Otherwise, an infinite loop might occur. Fix it by explicitly checking for 0 step. Fixes: ef0a0757bbea ("drm/i915/dp: compute config for 128b/132b SST w/o DSC") Reported-by: Imre Deak Closes: https://lore.kernel.org/r/Z6I0knh2Kt5T0JrT@ideak-desk.fi.intel.com Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250204154925.3001781-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index ff3ae5db4b54..cc6e4ca37519 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -378,6 +378,10 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, break; } + + /* Allow using zero step to indicate one try */ + if (!bpp_step_x16) + break; } if (slots < 0) { -- cgit v1.2.3-59-g8ed1b From ebac36ea8ad55b7c08ceaef0e3fa408c8cffacc6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 3 Feb 2025 18:08:34 +0200 Subject: drm/i915/dp: Add support for DP UHBR SST DSC Drop the UHBR limitation from DP SST DSC, and handle SST DSC bandwidth computation for UHBR using intel_dp_mtp_tu_compute_config(). Cc: Imre Deak Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250203160834.2708027-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 35 +++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e9a9f1f8d353..09211ae38d96 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1958,15 +1958,37 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp, for (lane_count = limits->min_lane_count; lane_count <= limits->max_lane_count; lane_count <<= 1) { - if (!is_bw_sufficient_for_dsc_config(dsc_bpp_x16, link_rate, - lane_count, adjusted_mode->clock, - pipe_config->output_format, - timeslots)) - continue; + /* + * FIXME: intel_dp_mtp_tu_compute_config() requires + * ->lane_count and ->port_clock set before we know + * they'll work. If we end up failing altogether, + * they'll remain in crtc state. This shouldn't matter, + * as we'd then bail out from compute config, but it's + * just ugly. + */ pipe_config->lane_count = lane_count; pipe_config->port_clock = link_rate; + if (drm_dp_is_uhbr_rate(link_rate)) { + int ret; + + ret = intel_dp_mtp_tu_compute_config(intel_dp, + pipe_config, + conn_state, + dsc_bpp_x16, + dsc_bpp_x16, + 0, true); + if (ret) + continue; + } else { + if (!is_bw_sufficient_for_dsc_config(dsc_bpp_x16, link_rate, + lane_count, adjusted_mode->clock, + pipe_config->output_format, + timeslots)) + continue; + } + return 0; } } @@ -2493,9 +2515,6 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp, limits->min_rate = intel_dp_min_link_rate(intel_dp); limits->max_rate = intel_dp_max_link_rate(intel_dp); - /* FIXME 128b/132b SST+DSC support missing */ - if (!is_mst && dsc) - limits->max_rate = min(limits->max_rate, 810000); limits->min_rate = min(limits->min_rate, limits->max_rate); limits->min_lane_count = intel_dp_min_lane_count(intel_dp); -- cgit v1.2.3-59-g8ed1b From dac328dea701ed1fde2b67176fe3c3a818536441 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Fri, 31 Jan 2025 11:15:02 +0530 Subject: drm/xe/hwmon: expose package and vram temperature Add hwmon support for temp2_input and temp3_input attributes, which will expose package and vram temperature in millidegree Celsius. With this in place we can monitor temperature using lm-sensors tool. v2: Reuse existing channels (Badal, Karthik) Signed-off-by: Raag Jadav Reviewed-by: Andi Shyti Reviewed-by: Badal Nilawar Link: https://patchwork.freedesktop.org/patch/msgid/20250131054502.1528555-1-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- .../ABI/testing/sysfs-driver-intel-xe-hwmon | 16 ++++++ drivers/gpu/drm/xe/regs/xe_mchbar_regs.h | 3 ++ drivers/gpu/drm/xe/regs/xe_pcode_regs.h | 2 + drivers/gpu/drm/xe/xe_hwmon.c | 60 ++++++++++++++++++++++ 4 files changed, 81 insertions(+) (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon index d792a56f59ac..9bce281314df 100644 --- a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon +++ b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon @@ -108,3 +108,19 @@ Contact: intel-xe@lists.freedesktop.org Description: RO. Package current voltage in millivolt. Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/temp2_input +Date: March 2025 +KernelVersion: 6.14 +Contact: intel-xe@lists.freedesktop.org +Description: RO. Package temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon/temp3_input +Date: March 2025 +KernelVersion: 6.14 +Contact: intel-xe@lists.freedesktop.org +Description: RO. VRAM temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. diff --git a/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h b/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h index 519dd1067a19..f5e5234857c1 100644 --- a/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h @@ -34,6 +34,9 @@ #define PCU_CR_PACKAGE_ENERGY_STATUS XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x593c) +#define PCU_CR_PACKAGE_TEMPERATURE XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x5978) +#define TEMP_MASK REG_GENMASK(7, 0) + #define PCU_CR_PACKAGE_RAPL_LIMIT XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x59a0) #define PKG_PWR_LIM_1 REG_GENMASK(14, 0) #define PKG_PWR_LIM_1_EN REG_BIT(15) diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h index 0b0b49d850ae..8846eb9ce2a4 100644 --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h @@ -21,6 +21,8 @@ #define BMG_PACKAGE_POWER_SKU XE_REG(0x138098) #define BMG_PACKAGE_POWER_SKU_UNIT XE_REG(0x1380dc) #define BMG_PACKAGE_ENERGY_STATUS XE_REG(0x138120) +#define BMG_VRAM_TEMPERATURE XE_REG(0x1382c0) +#define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) #define BMG_PACKAGE_RAPL_LIMIT XE_REG(0x138440) #define BMG_PLATFORM_ENERGY_STATUS XE_REG(0x138458) #define BMG_PLATFORM_POWER_LIMIT XE_REG(0x138460) diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index fde56dad3ab7..7f327e334212 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "regs/xe_gt_regs.h" @@ -20,6 +21,7 @@ #include "xe_pm.h" enum xe_hwmon_reg { + REG_TEMP, REG_PKG_RAPL_LIMIT, REG_PKG_POWER_SKU, REG_PKG_POWER_SKU_UNIT, @@ -36,6 +38,7 @@ enum xe_hwmon_reg_operation { enum xe_hwmon_channel { CHANNEL_CARD, CHANNEL_PKG, + CHANNEL_VRAM, CHANNEL_MAX, }; @@ -84,6 +87,19 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg struct xe_device *xe = hwmon->xe; switch (hwmon_reg) { + case REG_TEMP: + if (xe->info.platform == XE_BATTLEMAGE) { + if (channel == CHANNEL_PKG) + return BMG_PACKAGE_TEMPERATURE; + else if (channel == CHANNEL_VRAM) + return BMG_VRAM_TEMPERATURE; + } else if (xe->info.platform == XE_DG2) { + if (channel == CHANNEL_PKG) + return PCU_CR_PACKAGE_TEMPERATURE; + else if (channel == CHANNEL_VRAM) + return BMG_VRAM_TEMPERATURE; + } + break; case REG_PKG_RAPL_LIMIT: if (xe->info.platform == XE_BATTLEMAGE) { if (channel == CHANNEL_PKG) @@ -431,6 +447,8 @@ static const struct attribute_group *hwmon_groups[] = { }; static const struct hwmon_channel_info * const hwmon_info[] = { + HWMON_CHANNEL_INFO(temp, HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL), HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT | HWMON_P_LABEL), HWMON_CHANNEL_INFO(curr, HWMON_C_LABEL, HWMON_C_CRIT | HWMON_C_LABEL), @@ -506,6 +524,36 @@ static void xe_hwmon_get_voltage(struct xe_hwmon *hwmon, int channel, long *valu *value = DIV_ROUND_CLOSEST(REG_FIELD_GET(VOLTAGE_MASK, reg_val) * 2500, SF_VOLTAGE); } +static umode_t +xe_hwmon_temp_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) +{ + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_label: + return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_TEMP, channel)) ? 0444 : 0; + default: + return 0; + } +} + +static int +xe_hwmon_temp_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) +{ + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); + u64 reg_val; + + switch (attr) { + case hwmon_temp_input: + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); + + /* HW register value is in degrees Celsius, convert to millidegrees. */ + *val = REG_FIELD_GET(TEMP_MASK, reg_val) * MILLIDEGREE_PER_DEGREE; + return 0; + default: + return -EOPNOTSUPP; + } +} + static umode_t xe_hwmon_power_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) { @@ -667,6 +715,9 @@ xe_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type, xe_pm_runtime_get(hwmon->xe); switch (type) { + case hwmon_temp: + ret = xe_hwmon_temp_is_visible(hwmon, attr, channel); + break; case hwmon_power: ret = xe_hwmon_power_is_visible(hwmon, attr, channel); break; @@ -699,6 +750,9 @@ xe_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, xe_pm_runtime_get(hwmon->xe); switch (type) { + case hwmon_temp: + ret = xe_hwmon_temp_read(hwmon, attr, channel, val); + break; case hwmon_power: ret = xe_hwmon_power_read(hwmon, attr, channel, val); break; @@ -752,6 +806,12 @@ static int xe_hwmon_read_label(struct device *dev, u32 attr, int channel, const char **str) { switch (type) { + case hwmon_temp: + if (channel == CHANNEL_PKG) + *str = "pkg"; + else if (channel == CHANNEL_VRAM) + *str = "vram"; + return 0; case hwmon_power: case hwmon_energy: case hwmon_curr: -- cgit v1.2.3-59-g8ed1b From bdcdb913c2d36447ea49d33774e5d6093c55d6f7 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Fri, 24 Jan 2025 16:12:34 -0300 Subject: drm/i915/dmc_wl: Do not check for DMC payload Enabling and disabling of DMC wakelock is already coupled with enabling and disabling of dynamic DC states, which already depend on the DMC being properly loaded. As such, we do not need to check if we already have a DMC payload parsed in __intel_dmc_wl_supported(). Furthermore, the presence of such a check causes inconsistencies in the refcount if the following sequence of events happen: 1. A call to one of the register accessors from intel_de.h is done before the DMC payload is parsed. That causes intel_dmc_wl_get() to be called. Suppose the register offset qualifies as needing the wakelock. In normal circumstances, the refcount would be incremented, but, because __intel_dmc_wl_supported() returns false, the refcount is untouched. 2. In a separate worker thread, the DMC firmware is parsed. Parsing of the DMC payload is finished before the corresponding intel_dmc_wl_put() from (1) is called. 3. When in the context of (1), intel_dmc_wl_put() gets called, now we have __intel_dmc_wl_supported() returning true and we hit the warning, because the code doesn't expect a zero refcount. Let's remove that check, since it is unnecessary and causes the inconsistency illustrated above. Reviewed-by: Krzysztof Karas Reviewed-by: Luca Coelho Link: https://patchwork.freedesktop.org/patch/msgid/20250124191250.56833-1-gustavo.sousa@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 86ba159b683c..7e2ce0c2f6c3 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -10,7 +10,6 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_de.h" -#include "intel_dmc.h" #include "intel_dmc_regs.h" #include "intel_dmc_wl.h" @@ -283,7 +282,7 @@ static bool intel_dmc_wl_check_range(struct intel_display *display, static bool __intel_dmc_wl_supported(struct intel_display *display) { - return display->params.enable_dmc_wl && intel_dmc_has_payload(display); + return display->params.enable_dmc_wl; } static void intel_dmc_wl_sanitize_param(struct intel_display *display) -- cgit v1.2.3-59-g8ed1b From 87b593d79864e6e82cb00aa3d837094a1643e272 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 31 Jan 2025 15:11:32 -0800 Subject: drm/i915/pmu: Drop custom hotplug code Since commit 4ba4f1afb6a9 ("perf: Generic hotplug support for a PMU with a scope"), there's generic support for system-wide counters and integration with cpu hotplug. The i915 counters are system-wide, even though the migration code is using the wrong topology mask: target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); So one could think the counter has core scope rather than system scope, which is not the case. That was never caught in tests since they would disable just one cpu at a time. After the removal of hotpluggable CPU0 in commit 5475abbde77f ("x86/smpboot: Remove the CPU0 hotplug kludge") and commit e59e74dc48a3 ("x86/topology: Remove CPU0 hotplug option") this became essentially non-testable for our systems. Using the generic hotplug code, the same cpu0 is still reported in cpumask - only if it was possible to unplug it, it would migrate to another cpu, so there isn't much a change in behavior. The one thing that changes is the return code for perf_event_open() if an invalid cpu is used: previously i915 would return -EINVAL, but generic perf code returns -ENODEV. That should be ok for all the users and not cause breakages. Cc: Kan Liang Cc: Peter Zijlstra (Intel) Cc: Vinay Belgaumkar Reviewed-by: Umesh Nerlige Ramappa Reviewed-by: Tvrtko Ursulin Reviewed-by: Kan Liang Link: https://patchwork.freedesktop.org/patch/msgid/20250131231304.4151998-2-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/i915/i915_module.c | 2 - drivers/gpu/drm/i915/i915_pmu.c | 114 +------------------------------------ drivers/gpu/drm/i915/i915_pmu.h | 11 ---- 3 files changed, 1 insertion(+), 126 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_module.c b/drivers/gpu/drm/i915/i915_module.c index 7ed6d70389af..7affe07f84f4 100644 --- a/drivers/gpu/drm/i915/i915_module.c +++ b/drivers/gpu/drm/i915/i915_module.c @@ -71,8 +71,6 @@ static const struct { { .init = i915_vma_resource_module_init, .exit = i915_vma_resource_module_exit }, { .init = i915_mock_selftests }, - { .init = i915_pmu_init, - .exit = i915_pmu_exit }, { .init = i915_pci_register_driver, .exit = i915_pci_unregister_driver }, { .init = i915_perf_sysctl_register, diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 2eecd42f61ba..69a109d02116 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -28,9 +28,6 @@ BIT(I915_SAMPLE_WAIT) | \ BIT(I915_SAMPLE_SEMA)) -static cpumask_t i915_pmu_cpumask; -static unsigned int i915_pmu_target_cpu = -1; - static struct i915_pmu *event_to_pmu(struct perf_event *event) { return container_of(event->pmu, struct i915_pmu, base); @@ -642,10 +639,6 @@ static int i915_pmu_event_init(struct perf_event *event) if (event->cpu < 0) return -EINVAL; - /* only allow running on one cpu at a time */ - if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask)) - return -EINVAL; - if (is_engine_event(event)) ret = engine_event_init(event); else @@ -935,23 +928,6 @@ static ssize_t i915_pmu_event_show(struct device *dev, return sprintf(buf, "config=0x%lx\n", eattr->val); } -static ssize_t cpumask_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask); -} - -static DEVICE_ATTR_RO(cpumask); - -static struct attribute *i915_cpumask_attrs[] = { - &dev_attr_cpumask.attr, - NULL, -}; - -static const struct attribute_group i915_pmu_cpumask_attr_group = { - .attrs = i915_cpumask_attrs, -}; - #define __event(__counter, __name, __unit) \ { \ .counter = (__counter), \ @@ -1168,92 +1144,12 @@ static void free_event_attributes(struct i915_pmu *pmu) pmu->pmu_attr = NULL; } -static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node) -{ - struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node); - - /* Select the first online CPU as a designated reader. */ - if (cpumask_empty(&i915_pmu_cpumask)) - cpumask_set_cpu(cpu, &i915_pmu_cpumask); - - return 0; -} - -static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node) -{ - struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node); - unsigned int target = i915_pmu_target_cpu; - - /* - * Unregistering an instance generates a CPU offline event which we must - * ignore to avoid incorrectly modifying the shared i915_pmu_cpumask. - */ - if (!pmu->registered) - return 0; - - if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) { - target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); - - /* Migrate events if there is a valid target */ - if (target < nr_cpu_ids) { - cpumask_set_cpu(target, &i915_pmu_cpumask); - i915_pmu_target_cpu = target; - } - } - - if (target < nr_cpu_ids && target != pmu->cpuhp.cpu) { - perf_pmu_migrate_context(&pmu->base, cpu, target); - pmu->cpuhp.cpu = target; - } - - return 0; -} - -static enum cpuhp_state cpuhp_state = CPUHP_INVALID; - -int i915_pmu_init(void) -{ - int ret; - - ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, - "perf/x86/intel/i915:online", - i915_pmu_cpu_online, - i915_pmu_cpu_offline); - if (ret < 0) - pr_notice("Failed to setup cpuhp state for i915 PMU! (%d)\n", - ret); - else - cpuhp_state = ret; - - return 0; -} - -void i915_pmu_exit(void) -{ - if (cpuhp_state != CPUHP_INVALID) - cpuhp_remove_multi_state(cpuhp_state); -} - -static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu) -{ - if (cpuhp_state == CPUHP_INVALID) - return -EINVAL; - - return cpuhp_state_add_instance(cpuhp_state, &pmu->cpuhp.node); -} - -static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu) -{ - cpuhp_state_remove_instance(cpuhp_state, &pmu->cpuhp.node); -} - void i915_pmu_register(struct drm_i915_private *i915) { struct i915_pmu *pmu = &i915->pmu; const struct attribute_group *attr_groups[] = { &i915_pmu_format_attr_group, &pmu->events_attr_group, - &i915_pmu_cpumask_attr_group, NULL }; int ret = -ENOMEM; @@ -1261,7 +1157,6 @@ void i915_pmu_register(struct drm_i915_private *i915) spin_lock_init(&pmu->lock); hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pmu->timer.function = i915_sample; - pmu->cpuhp.cpu = -1; init_rc6(pmu); if (IS_DGFX(i915)) { @@ -1290,6 +1185,7 @@ void i915_pmu_register(struct drm_i915_private *i915) pmu->base.module = THIS_MODULE; pmu->base.task_ctx_nr = perf_invalid_context; + pmu->base.scope = PERF_PMU_SCOPE_SYS_WIDE; pmu->base.event_init = i915_pmu_event_init; pmu->base.add = i915_pmu_event_add; pmu->base.del = i915_pmu_event_del; @@ -1301,16 +1197,10 @@ void i915_pmu_register(struct drm_i915_private *i915) if (ret) goto err_groups; - ret = i915_pmu_register_cpuhp_state(pmu); - if (ret) - goto err_unreg; - pmu->registered = true; return; -err_unreg: - perf_pmu_unregister(&pmu->base); err_groups: kfree(pmu->base.attr_groups); err_attr: @@ -1334,8 +1224,6 @@ void i915_pmu_unregister(struct drm_i915_private *i915) hrtimer_cancel(&pmu->timer); - i915_pmu_unregister_cpuhp_state(pmu); - perf_pmu_unregister(&pmu->base); kfree(pmu->base.attr_groups); if (IS_DGFX(i915)) diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 8e66d63d0c9f..53bce3d8bfba 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -56,13 +56,6 @@ struct i915_pmu_sample { }; struct i915_pmu { - /** - * @cpuhp: Struct used for CPU hotplug handling. - */ - struct { - struct hlist_node node; - unsigned int cpu; - } cpuhp; /** * @base: PMU base. */ @@ -155,15 +148,11 @@ struct i915_pmu { }; #ifdef CONFIG_PERF_EVENTS -int i915_pmu_init(void); -void i915_pmu_exit(void); void i915_pmu_register(struct drm_i915_private *i915); void i915_pmu_unregister(struct drm_i915_private *i915); void i915_pmu_gt_parked(struct intel_gt *gt); void i915_pmu_gt_unparked(struct intel_gt *gt); #else -static inline int i915_pmu_init(void) { return 0; } -static inline void i915_pmu_exit(void) {} static inline void i915_pmu_register(struct drm_i915_private *i915) {} static inline void i915_pmu_unregister(struct drm_i915_private *i915) {} static inline void i915_pmu_gt_parked(struct intel_gt *gt) {} -- cgit v1.2.3-59-g8ed1b From 082795b2c67f264d1ec30cde723b7f24c448bfa7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:58:38 +0200 Subject: drm/i915/hdmi: move declarations for hsw_read/write_infoframe() to the right place The functions are located in intel_hdmi.c, put the declarations in intel_hdmi.h. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/e8cd28a3c46f06b9654df8b7990e1e6a1d9e18c1.1738677489.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdmi.h | 9 +++++++++ drivers/gpu/drm/i915/display/intel_lspcon.h | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index 38deaeb302a2..d237fe08c3e6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -62,4 +62,13 @@ int intel_hdmi_dsc_get_num_slices(const struct intel_crtc_state *crtc_state, int hdmi_max_slices, int hdmi_throughput); int intel_hdmi_dsc_get_slice_height(int vactive); +void hsw_write_infoframe(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + unsigned int type, + const void *frame, ssize_t len); +void hsw_read_infoframe(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + unsigned int type, + void *frame, ssize_t len); + #endif /* __INTEL_HDMI_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h index e19e10492b05..47f9ae77b328 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.h +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h @@ -35,13 +35,5 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config); u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config); -void hsw_write_infoframe(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - unsigned int type, - const void *frame, ssize_t len); -void hsw_read_infoframe(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - unsigned int type, - void *frame, ssize_t len); #endif /* __INTEL_LSPCON_H__ */ -- cgit v1.2.3-59-g8ed1b From 34176697bda3066de583deb5e569e2d77d5dc7f0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:58:39 +0200 Subject: drm/i915/lspcon: add intel_lspcon_active() and use it Hide the direct lspcon->active use behind intel_lspcon_active(). Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/3eabe0cb07a84c63119ea893e149de410b4356b0.1738677489.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_ddi.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dp.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_lspcon.c | 7 +++++++ drivers/gpu/drm/i915/display/intel_lspcon.h | 1 + 4 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index dc319f37b1be..3e85ef281f1e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3025,7 +3025,7 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state, /* FIXME precompute everything properly */ /* FIXME how do we turn infoframes off again? */ - if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp)) + if (intel_lspcon_active(dig_port) && intel_dp_has_hdmi_sink(&dig_port->dp)) dig_port->set_infoframes(encoder, crtc_state->has_infoframe, crtc_state, conn_state); @@ -3381,7 +3381,7 @@ static void intel_ddi_enable_dp(struct intel_atomic_state *state, drm_connector_update_privacy_screen(conn_state); intel_edp_backlight_on(crtc_state, conn_state); - if (!dig_port->lspcon.active || intel_dp_has_hdmi_sink(&dig_port->dp)) + if (!intel_lspcon_active(dig_port) || intel_dp_has_hdmi_sink(&dig_port->dp)) intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); trans_port_sync_stop_link_train(state, encoder, crtc_state); @@ -4082,7 +4082,7 @@ static void intel_ddi_read_func_ctl_dp_sst(struct intel_encoder *encoder, intel_de_read(display, dp_tp_ctl_reg(encoder, crtc_state)) & DP_TP_CTL_FEC_ENABLE; - if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp)) + if (intel_lspcon_active(dig_port) && intel_dp_has_hdmi_sink(&dig_port->dp)) crtc_state->infoframes.enable |= intel_lspcon_infoframes_enabled(encoder, crtc_state); else diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 09211ae38d96..860f246aeb06 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3519,9 +3519,10 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode); } else { + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp); - lspcon_resume(dp_to_dig_port(intel_dp)); + lspcon_resume(dig_port); /* Write the source OUI as early as possible */ intel_dp_init_source_oui(intel_dp); @@ -3537,7 +3538,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) msleep(1); } - if (ret == 1 && lspcon->active) + if (ret == 1 && intel_lspcon_active(dig_port)) lspcon_wait_pcon_mode(lspcon); } @@ -5588,7 +5589,7 @@ intel_dp_update_420(struct intel_dp *intel_dp) intel_dp->downstream_ports); /* on-board LSPCON always assumed to support 4:4:4->4:2:0 conversion */ intel_dp->dfp.ycbcr_444_to_420 = - dp_to_dig_port(intel_dp)->lspcon.active || + intel_lspcon_active(dp_to_dig_port(intel_dp)) || drm_dp_downstream_444_to_420_conversion(intel_dp->dpcd, intel_dp->downstream_ports); intel_dp->dfp.rgb_to_ycbcr = diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 0c8bf477c2fb..e54aad8a5f7f 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -689,6 +689,13 @@ bool lspcon_init(struct intel_digital_port *dig_port) return true; } +bool intel_lspcon_active(struct intel_digital_port *dig_port) +{ + struct intel_lspcon *lspcon = &dig_port->lspcon; + + return lspcon->active; +} + u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config) { diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h index 47f9ae77b328..4c8ba3ddbac4 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.h +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h @@ -16,6 +16,7 @@ struct intel_encoder; struct intel_lspcon; bool lspcon_init(struct intel_digital_port *dig_port); +bool intel_lspcon_active(struct intel_digital_port *dig_port); void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon); void lspcon_resume(struct intel_digital_port *dig_port); void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon); -- cgit v1.2.3-59-g8ed1b From ab945e9a4e73e8eb3f54ea34dffd22eb70696c03 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:58:40 +0200 Subject: drm/i915/lspcon: change signature of lspcon_detect_hdr_capability() Switch from struct intel_lspcon to struct intel_digital_port to unify, and return the value so the caller doesn't have to look at lspcon->hdr_detected directly. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/6f249f5c537a16a6762faddffd6a95cbf61cf077.1738677489.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 4 +--- drivers/gpu/drm/i915/display/intel_lspcon.c | 5 ++++- drivers/gpu/drm/i915/display/intel_lspcon.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 860f246aeb06..3b2a20553f93 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5863,7 +5863,6 @@ intel_dp_connector_register(struct drm_connector *connector) struct intel_display *display = to_intel_display(connector->dev); struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct intel_lspcon *lspcon = &dig_port->lspcon; int ret; ret = intel_connector_register(connector); @@ -5886,8 +5885,7 @@ intel_dp_connector_register(struct drm_connector *connector) * efficiently and streamlined. */ if (lspcon_init(dig_port)) { - lspcon_detect_hdr_capability(lspcon); - if (lspcon->hdr_supported) + if (lspcon_detect_hdr_capability(dig_port)) drm_connector_attach_hdr_output_metadata_property(connector); } diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index e54aad8a5f7f..2dd2b700b0f3 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -121,8 +121,9 @@ static u32 get_hdr_status_reg(struct intel_lspcon *lspcon) return DPCD_PARADE_LSPCON_HDR_STATUS; } -void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon) +bool lspcon_detect_hdr_capability(struct intel_digital_port *dig_port) { + struct intel_lspcon *lspcon = &dig_port->lspcon; struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); struct intel_display *display = to_intel_display(intel_dp); u8 hdr_caps; @@ -138,6 +139,8 @@ void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon) drm_dbg_kms(display->drm, "LSPCON capable of HDR\n"); lspcon->hdr_supported = true; } + + return lspcon->hdr_supported; } static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h index 4c8ba3ddbac4..18cc15e5221d 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.h +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h @@ -17,7 +17,7 @@ struct intel_lspcon; bool lspcon_init(struct intel_digital_port *dig_port); bool intel_lspcon_active(struct intel_digital_port *dig_port); -void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon); +bool lspcon_detect_hdr_capability(struct intel_digital_port *dig_port); void lspcon_resume(struct intel_digital_port *dig_port); void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon); void lspcon_write_infoframe(struct intel_encoder *encoder, -- cgit v1.2.3-59-g8ed1b From 295e276a6af6fadfe31c1afe27a2c670e4f9cbc3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:58:41 +0200 Subject: drm/i915/lspcon: change signature of lspcon_wait_pcon_mode() Switch from struct intel_lspcon to struct intel_digital_port to unify. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/84a00791d3d7ee4e34c1224ef7471918546635aa.1738677489.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 3 +-- drivers/gpu/drm/i915/display/intel_lspcon.c | 4 +++- drivers/gpu/drm/i915/display/intel_lspcon.h | 4 +--- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3b2a20553f93..e4676339c3ea 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3520,7 +3520,6 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode); } else { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp); lspcon_resume(dig_port); @@ -3539,7 +3538,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) } if (ret == 1 && intel_lspcon_active(dig_port)) - lspcon_wait_pcon_mode(lspcon); + lspcon_wait_pcon_mode(dig_port); } if (ret != 1) diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 2dd2b700b0f3..45b63fea3642 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -656,8 +656,10 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, return val; } -void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon) +void lspcon_wait_pcon_mode(struct intel_digital_port *dig_port) { + struct intel_lspcon *lspcon = &dig_port->lspcon; + lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON); } diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h index 18cc15e5221d..20581af1ddb2 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.h +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h @@ -8,18 +8,16 @@ #include -struct drm_connector; struct drm_connector_state; struct intel_crtc_state; struct intel_digital_port; struct intel_encoder; -struct intel_lspcon; bool lspcon_init(struct intel_digital_port *dig_port); bool intel_lspcon_active(struct intel_digital_port *dig_port); bool lspcon_detect_hdr_capability(struct intel_digital_port *dig_port); void lspcon_resume(struct intel_digital_port *dig_port); -void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon); +void lspcon_wait_pcon_mode(struct intel_digital_port *dig_port); void lspcon_write_infoframe(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, unsigned int type, -- cgit v1.2.3-59-g8ed1b From 9b98776490ac28c150811f4fa4f88b81a4c97aa5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:58:42 +0200 Subject: drm/i915/lspcon: remove dp_to_lspcon(), hide enc_to_intel_lspcon() There are no users left for dp_to_lspcon(), remove it. The only two users of enc_to_intel_lspcon() are in intel_lspcon.c, so hide it there. v2: Rebase Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/ea14ba07b88ba5ed65d832c89a3415b7a91edea9.1738677489.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_types.h | 12 ------------ drivers/gpu/drm/i915/display/intel_lspcon.c | 5 +++++ 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f1a9ab4ae85a..37b1a216b13b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1983,24 +1983,12 @@ static inline bool intel_encoder_is_hdmi(struct intel_encoder *encoder) } } -static inline struct intel_lspcon * -enc_to_intel_lspcon(struct intel_encoder *encoder) -{ - return &enc_to_dig_port(encoder)->lspcon; -} - static inline struct intel_digital_port * dp_to_dig_port(struct intel_dp *intel_dp) { return container_of(intel_dp, struct intel_digital_port, dp); } -static inline struct intel_lspcon * -dp_to_lspcon(struct intel_dp *intel_dp) -{ - return &dp_to_dig_port(intel_dp)->lspcon; -} - static inline struct intel_digital_port * hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) { diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 45b63fea3642..02c22a981fe1 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -55,6 +55,11 @@ #define LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7) #define LSPCON_PARADE_AVI_IF_DATA_SIZE 32 +static struct intel_lspcon *enc_to_intel_lspcon(struct intel_encoder *encoder) +{ + return &enc_to_dig_port(encoder)->lspcon; +} + static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon) { struct intel_digital_port *dig_port = -- cgit v1.2.3-59-g8ed1b From 8de6a113ad210194e22211f90f224904e407a4a0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:58:43 +0200 Subject: drm/i915/lspcon: rename interfaces to intel_lspcon_* to unify Rename all the main functions to have intel_lspcon_ prefix. Keep the infoframes hooks named lspcon_ for now, and grouped together, as there'd be a clash with intel_lspcon_infoframes_enabled(). Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/15e8c4133aee89181e6776a44e58f2573cfe23f2.1738677489.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 10 +++++----- drivers/gpu/drm/i915/display/intel_lspcon.c | 10 +++++----- drivers/gpu/drm/i915/display/intel_lspcon.h | 14 ++++++++------ 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e4676339c3ea..7127cda64828 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3521,7 +3521,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) } else { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - lspcon_resume(dig_port); + intel_lspcon_resume(dig_port); /* Write the source OUI as early as possible */ intel_dp_init_source_oui(intel_dp); @@ -3538,7 +3538,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) } if (ret == 1 && intel_lspcon_active(dig_port)) - lspcon_wait_pcon_mode(dig_port); + intel_lspcon_wait_pcon_mode(dig_port); } if (ret != 1) @@ -5388,7 +5388,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) if (drm_WARN_ON(display->drm, intel_dp_is_edp(intel_dp))) return connector_status_connected; - lspcon_resume(dig_port); + intel_lspcon_resume(dig_port); if (!intel_dp_get_dpcd(intel_dp)) return connector_status_disconnected; @@ -5883,8 +5883,8 @@ intel_dp_connector_register(struct drm_connector *connector) * ToDo: Clean this up to handle lspcon init and resume more * efficiently and streamlined. */ - if (lspcon_init(dig_port)) { - if (lspcon_detect_hdr_capability(dig_port)) + if (intel_lspcon_init(dig_port)) { + if (intel_lspcon_detect_hdr_capability(dig_port)) drm_connector_attach_hdr_output_metadata_property(connector); } diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 02c22a981fe1..63c1afa30b05 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -126,7 +126,7 @@ static u32 get_hdr_status_reg(struct intel_lspcon *lspcon) return DPCD_PARADE_LSPCON_HDR_STATUS; } -bool lspcon_detect_hdr_capability(struct intel_digital_port *dig_port) +bool intel_lspcon_detect_hdr_capability(struct intel_digital_port *dig_port) { struct intel_lspcon *lspcon = &dig_port->lspcon; struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); @@ -661,14 +661,14 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, return val; } -void lspcon_wait_pcon_mode(struct intel_digital_port *dig_port) +void intel_lspcon_wait_pcon_mode(struct intel_digital_port *dig_port) { struct intel_lspcon *lspcon = &dig_port->lspcon; lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON); } -bool lspcon_init(struct intel_digital_port *dig_port) +bool intel_lspcon_init(struct intel_digital_port *dig_port) { struct intel_display *display = to_intel_display(dig_port); struct intel_dp *intel_dp = &dig_port->dp; @@ -714,7 +714,7 @@ u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder, return dig_port->infoframes_enabled(encoder, pipe_config); } -void lspcon_resume(struct intel_digital_port *dig_port) +void intel_lspcon_resume(struct intel_digital_port *dig_port) { struct intel_display *display = to_intel_display(dig_port); struct intel_lspcon *lspcon = &dig_port->lspcon; @@ -724,7 +724,7 @@ void lspcon_resume(struct intel_digital_port *dig_port) return; if (!lspcon->active) { - if (!lspcon_init(dig_port)) { + if (!intel_lspcon_init(dig_port)) { drm_err(display->drm, "LSPCON init failed on port %c\n", port_name(dig_port->base.port)); return; diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h index 20581af1ddb2..41d142a5c440 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.h +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h @@ -13,11 +13,15 @@ struct intel_crtc_state; struct intel_digital_port; struct intel_encoder; -bool lspcon_init(struct intel_digital_port *dig_port); +bool intel_lspcon_init(struct intel_digital_port *dig_port); bool intel_lspcon_active(struct intel_digital_port *dig_port); -bool lspcon_detect_hdr_capability(struct intel_digital_port *dig_port); -void lspcon_resume(struct intel_digital_port *dig_port); -void lspcon_wait_pcon_mode(struct intel_digital_port *dig_port); +bool intel_lspcon_detect_hdr_capability(struct intel_digital_port *dig_port); +void intel_lspcon_resume(struct intel_digital_port *dig_port); +void intel_lspcon_wait_pcon_mode(struct intel_digital_port *dig_port); +u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config); + +/* digital port infoframes hooks */ void lspcon_write_infoframe(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, unsigned int type, @@ -32,7 +36,5 @@ void lspcon_set_infoframes(struct intel_encoder *encoder, const struct drm_connector_state *conn_state); u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config); -u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config); #endif /* __INTEL_LSPCON_H__ */ -- cgit v1.2.3-59-g8ed1b From bb68ce5daf1ac73222afbe3f8fa7ad6edd150c72 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:42:26 +0200 Subject: drm/i915/display: convert intel_ddi_buf_trans.c to struct intel_display Going forward, struct intel_display is the main device data structure for display. Switch to it. For MISSING_CASE(), log the PCI ID instead of the platform to get rid of the i915_drv.h dependency. Reviewed-by: Rodrigo Vivi Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20250204134228.2934744-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c | 58 ++++++++++++---------- 1 file changed, 33 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index 9389b295036e..a238be5bc455 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -3,13 +3,13 @@ * Copyright © 2020 Intel Corporation */ -#include "i915_drv.h" +#include "i915_utils.h" +#include "intel_cx0_phy.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dp.h" -#include "intel_cx0_phy.h" /* HDMI/DVI modes ignore everything but the last 2 items. So we share * them for both DP and FDI transports, allowing those ports to @@ -1407,10 +1407,10 @@ tgl_get_combo_buf_trans_dp(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, int *n_entries) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); if (crtc_state->port_clock > 270000) { - if (IS_TIGERLAKE_UY(dev_priv)) { + if (display->platform.tigerlake_uy) { return intel_get_buf_trans(&tgl_uy_combo_phy_trans_dp_hbr2, n_entries); } else { @@ -1709,59 +1709,67 @@ mtl_get_c20_buf_trans(struct intel_encoder *encoder, void intel_ddi_buf_trans_init(struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); - if (DISPLAY_VER(i915) >= 14) { + if (DISPLAY_VER(display) >= 14) { if (intel_encoder_is_c10phy(encoder)) encoder->get_buf_trans = mtl_get_c10_buf_trans; else encoder->get_buf_trans = mtl_get_c20_buf_trans; - } else if (IS_DG2(i915)) { + } else if (display->platform.dg2) { encoder->get_buf_trans = dg2_get_snps_buf_trans; - } else if (IS_ALDERLAKE_P(i915)) { + } else if (display->platform.alderlake_p) { if (intel_encoder_is_combo(encoder)) encoder->get_buf_trans = adlp_get_combo_buf_trans; else encoder->get_buf_trans = adlp_get_dkl_buf_trans; - } else if (IS_ALDERLAKE_S(i915)) { + } else if (display->platform.alderlake_s) { encoder->get_buf_trans = adls_get_combo_buf_trans; - } else if (IS_ROCKETLAKE(i915)) { + } else if (display->platform.rocketlake) { encoder->get_buf_trans = rkl_get_combo_buf_trans; - } else if (IS_DG1(i915)) { + } else if (display->platform.dg1) { encoder->get_buf_trans = dg1_get_combo_buf_trans; - } else if (DISPLAY_VER(i915) >= 12) { + } else if (DISPLAY_VER(display) >= 12) { if (intel_encoder_is_combo(encoder)) encoder->get_buf_trans = tgl_get_combo_buf_trans; else encoder->get_buf_trans = tgl_get_dkl_buf_trans; - } else if (DISPLAY_VER(i915) == 11) { - if (IS_JASPERLAKE(i915)) + } else if (DISPLAY_VER(display) == 11) { + if (display->platform.jasperlake) encoder->get_buf_trans = jsl_get_combo_buf_trans; - else if (IS_ELKHARTLAKE(i915)) + else if (display->platform.elkhartlake) encoder->get_buf_trans = ehl_get_combo_buf_trans; else if (intel_encoder_is_combo(encoder)) encoder->get_buf_trans = icl_get_combo_buf_trans; else encoder->get_buf_trans = icl_get_mg_buf_trans; - } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) { + } else if (display->platform.geminilake || display->platform.broxton) { encoder->get_buf_trans = bxt_get_buf_trans; - } else if (IS_COMETLAKE_ULX(i915) || IS_COFFEELAKE_ULX(i915) || IS_KABYLAKE_ULX(i915)) { + } else if (display->platform.cometlake_ulx || + display->platform.coffeelake_ulx || + display->platform.kabylake_ulx) { encoder->get_buf_trans = kbl_y_get_buf_trans; - } else if (IS_COMETLAKE_ULT(i915) || IS_COFFEELAKE_ULT(i915) || IS_KABYLAKE_ULT(i915)) { + } else if (display->platform.cometlake_ult || + display->platform.coffeelake_ult || + display->platform.kabylake_ult) { encoder->get_buf_trans = kbl_u_get_buf_trans; - } else if (IS_COMETLAKE(i915) || IS_COFFEELAKE(i915) || IS_KABYLAKE(i915)) { + } else if (display->platform.cometlake || + display->platform.coffeelake || + display->platform.kabylake) { encoder->get_buf_trans = kbl_get_buf_trans; - } else if (IS_SKYLAKE_ULX(i915)) { + } else if (display->platform.skylake_ulx) { encoder->get_buf_trans = skl_y_get_buf_trans; - } else if (IS_SKYLAKE_ULT(i915)) { + } else if (display->platform.skylake_ult) { encoder->get_buf_trans = skl_u_get_buf_trans; - } else if (IS_SKYLAKE(i915)) { + } else if (display->platform.skylake) { encoder->get_buf_trans = skl_get_buf_trans; - } else if (IS_BROADWELL(i915)) { + } else if (display->platform.broadwell) { encoder->get_buf_trans = bdw_get_buf_trans; - } else if (IS_HASWELL(i915)) { + } else if (display->platform.haswell) { encoder->get_buf_trans = hsw_get_buf_trans; } else { - MISSING_CASE(INTEL_INFO(i915)->platform); + struct pci_dev *pdev = to_pci_dev(display->drm->dev); + + MISSING_CASE(pdev->device); } } -- cgit v1.2.3-59-g8ed1b From f0453266763841585e6f7d9cb9cd3db18fbb5dbe Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:42:27 +0200 Subject: drm/i915/cdclk: switch to new platform checks Switch the IS_() checks to display->platform., and drop a number of struct drm_i915_private pointers in the process. While at it, replace /* NOOP */; with ; /* NOOP */ to avoid a checkpatch warning on misleading indentation. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250204134228.2934744-2-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cdclk.c | 159 ++++++++++++----------------- 1 file changed, 68 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index b520231833b7..753ba3e3a0b7 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -314,27 +314,26 @@ static unsigned int intel_hpll_vco(struct intel_display *display) [4] = 2666667, [5] = 4266667, }; - struct drm_i915_private *dev_priv = to_i915(display->drm); const unsigned int *vco_table; unsigned int vco; u8 tmp = 0; /* FIXME other chipsets? */ - if (IS_GM45(dev_priv)) + if (display->platform.gm45) vco_table = ctg_vco; - else if (IS_G45(dev_priv)) + else if (display->platform.g45) vco_table = elk_vco; - else if (IS_I965GM(dev_priv)) + else if (display->platform.i965gm) vco_table = cl_vco; - else if (IS_PINEVIEW(dev_priv)) + else if (display->platform.pineview) vco_table = pnv_vco; - else if (IS_G33(dev_priv)) + else if (display->platform.g33) vco_table = blb_vco; else return 0; - tmp = intel_de_read(display, - IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO); + tmp = intel_de_read(display, display->platform.pineview || + display->platform.mobile ? HPLLVCO_MOBILE : HPLLVCO); vco = vco_table[tmp & 0x7]; if (vco == 0) @@ -508,7 +507,6 @@ static void gm45_get_cdclk(struct intel_display *display, static void hsw_get_cdclk(struct intel_display *display, struct intel_cdclk_config *cdclk_config) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 lcpll = intel_de_read(display, LCPLL_CTL); u32 freq = lcpll & LCPLL_CLK_FREQ_MASK; @@ -518,7 +516,7 @@ static void hsw_get_cdclk(struct intel_display *display, cdclk_config->cdclk = 450000; else if (freq == LCPLL_CLK_FREQ_450) cdclk_config->cdclk = 450000; - else if (IS_HASWELL_ULT(dev_priv)) + else if (display->platform.haswell_ult) cdclk_config->cdclk = 337500; else cdclk_config->cdclk = 540000; @@ -535,7 +533,7 @@ static int vlv_calc_cdclk(struct intel_display *display, int min_cdclk) * Not sure what's wrong. For now use 200MHz only when all pipes * are off. */ - if (IS_VALLEYVIEW(dev_priv) && min_cdclk > freq_320) + if (display->platform.valleyview && min_cdclk > freq_320) return 400000; else if (min_cdclk > 266667) return freq_320; @@ -549,7 +547,7 @@ static u8 vlv_calc_voltage_level(struct intel_display *display, int cdclk) { struct drm_i915_private *dev_priv = to_i915(display->drm); - if (IS_VALLEYVIEW(dev_priv)) { + if (display->platform.valleyview) { if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ return 2; else if (cdclk >= 266667) @@ -585,7 +583,7 @@ static void vlv_get_cdclk(struct intel_display *display, vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); - if (IS_VALLEYVIEW(dev_priv)) + if (display->platform.valleyview) cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK) >> DSPFREQGUAR_SHIFT; else @@ -598,14 +596,14 @@ static void vlv_program_pfi_credits(struct intel_display *display) struct drm_i915_private *dev_priv = to_i915(display->drm); unsigned int credits, default_credits; - if (IS_CHERRYVIEW(dev_priv)) + if (display->platform.cherryview) default_credits = PFI_CREDIT(12); else default_credits = PFI_CREDIT(8); if (display->cdclk.hw.cdclk >= dev_priv->czclk_freq) { /* CHV suggested value is 31 or 63 */ - if (IS_CHERRYVIEW(dev_priv)) + if (display->platform.cherryview) credits = PFI_CREDIT_63; else credits = PFI_CREDIT(15); @@ -1142,7 +1140,7 @@ static void skl_set_cdclk(struct intel_display *display, * minimum 308MHz CDCLK. */ drm_WARN_ON_ONCE(display->drm, - IS_SKYLAKE(dev_priv) && vco == 8640000); + display->platform.skylake && vco == 8640000); ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, SKL_CDCLK_PREPARE_FOR_CHANGE, @@ -1662,10 +1660,9 @@ static void icl_readout_refclk(struct intel_display *display, static void bxt_de_pll_readout(struct intel_display *display, struct intel_cdclk_config *cdclk_config) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 val, ratio; - if (IS_DG2(dev_priv)) + if (display->platform.dg2) cdclk_config->ref = 38400; else if (DISPLAY_VER(display) >= 11) icl_readout_refclk(display, cdclk_config); @@ -2057,11 +2054,9 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct intel_display *displa static bool pll_enable_wa_needed(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - return (DISPLAY_VERx100(display) == 2000 || DISPLAY_VERx100(display) == 1400 || - IS_DG2(dev_priv)) && + display->platform.dg2) && display->cdclk.hw.vco > 0; } @@ -2069,7 +2064,6 @@ static u32 bxt_cdclk_ctl(struct intel_display *display, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) { - struct drm_i915_private *i915 = to_i915(display->drm); int cdclk = cdclk_config->cdclk; int vco = cdclk_config->vco; u16 waveform; @@ -2084,7 +2078,7 @@ static u32 bxt_cdclk_ctl(struct intel_display *display, * Disable SSA Precharge when CD clock frequency < 500 MHz, * enable otherwise. */ - if ((IS_GEMINILAKE(i915) || IS_BROXTON(i915)) && + if ((display->platform.geminilake || display->platform.broxton) && cdclk >= 500000) val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE; @@ -2144,8 +2138,8 @@ static void bxt_set_cdclk(struct intel_display *display, * mailbox communication, skip * this step. */ - if (DISPLAY_VER(display) >= 14 || IS_DG2(dev_priv)) - /* NOOP */; + if (DISPLAY_VER(display) >= 14 || display->platform.dg2) + ; /* NOOP */ else if (DISPLAY_VER(display) >= 11) ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, SKL_CDCLK_PREPARE_FOR_CHANGE, @@ -2186,7 +2180,7 @@ static void bxt_set_cdclk(struct intel_display *display, * NOOP - No Pcode communication needed for * Display versions 14 and beyond */; - else if (DISPLAY_VER(display) >= 11 && !IS_DG2(dev_priv)) + else if (DISPLAY_VER(display) >= 11 && !display->platform.dg2) ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, cdclk_config->voltage_level); if (DISPLAY_VER(display) < 11) { @@ -2318,9 +2312,7 @@ static void bxt_cdclk_uninit_hw(struct intel_display *display) */ void intel_cdclk_init_hw(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - if (DISPLAY_VER(display) >= 10 || IS_BROXTON(i915)) + if (DISPLAY_VER(display) >= 10 || display->platform.broxton) bxt_cdclk_init_hw(display); else if (DISPLAY_VER(display) == 9) skl_cdclk_init_hw(display); @@ -2335,9 +2327,7 @@ void intel_cdclk_init_hw(struct intel_display *display) */ void intel_cdclk_uninit_hw(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - if (DISPLAY_VER(display) >= 10 || IS_BROXTON(i915)) + if (DISPLAY_VER(display) >= 10 || display->platform.broxton) bxt_cdclk_uninit_hw(display); else if (DISPLAY_VER(display) == 9) skl_cdclk_uninit_hw(display); @@ -2438,10 +2428,8 @@ static bool intel_cdclk_can_cd2x_update(struct intel_display *display, const struct intel_cdclk_config *a, const struct intel_cdclk_config *b) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - /* Older hw doesn't have the capability */ - if (DISPLAY_VER(display) < 10 && !IS_BROXTON(dev_priv)) + if (DISPLAY_VER(display) < 10 && !display->platform.broxton) return false; /* @@ -2495,7 +2483,7 @@ static void intel_pcode_notify(struct intel_display *display, int ret; u32 update_mask = 0; - if (!IS_DG2(i915)) + if (!display->platform.dg2) return; update_mask = DISPLAY_TO_PCODE_UPDATE_MASK(cdclk, active_pipe_count, voltage_level); @@ -2681,7 +2669,6 @@ void intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - struct drm_i915_private *i915 = to_i915(display->drm); const struct intel_cdclk_state *old_cdclk_state = intel_atomic_get_old_cdclk_state(state); const struct intel_cdclk_state *new_cdclk_state = @@ -2693,7 +2680,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) &new_cdclk_state->actual)) return; - if (IS_DG2(i915)) + if (display->platform.dg2) intel_cdclk_pcode_pre_notify(state); if (new_cdclk_state->disable_pipes) { @@ -2735,7 +2722,6 @@ void intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - struct drm_i915_private *i915 = to_i915(display->drm); const struct intel_cdclk_state *old_cdclk_state = intel_atomic_get_old_cdclk_state(state); const struct intel_cdclk_state *new_cdclk_state = @@ -2746,7 +2732,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) &new_cdclk_state->actual)) return; - if (IS_DG2(i915)) + if (display->platform.dg2) intel_cdclk_pcode_post_notify(state); if (!new_cdclk_state->disable_pipes && @@ -2770,12 +2756,10 @@ static int intel_cdclk_ppc(struct intel_display *display, bool double_wide) /* max pixel rate as % of CDCLK (not accounting for PPC) */ static int intel_cdclk_guardband(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - if (DISPLAY_VER(display) >= 9 || - IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + display->platform.broadwell || display->platform.haswell) return 100; - else if (IS_CHERRYVIEW(dev_priv)) + else if (display->platform.cherryview) return 95; else return 90; @@ -2878,7 +2862,7 @@ static int intel_compute_min_cdclk(struct intel_atomic_state *state) * by changing the cd2x divider (see glk_cdclk_table[]) and * thus a full modeset won't be needed then. */ - if (IS_GEMINILAKE(dev_priv) && cdclk_state->active_pipes && + if (display->platform.geminilake && cdclk_state->active_pipes && !is_power_of_2(cdclk_state->active_pipes)) min_cdclk = max(min_cdclk, 2 * 96000); @@ -3232,7 +3216,6 @@ static bool intel_cdclk_need_serialize(struct intel_display *display, const struct intel_cdclk_state *old_cdclk_state, const struct intel_cdclk_state *new_cdclk_state) { - struct drm_i915_private *i915 = to_i915(display->drm); bool power_well_cnt_changed = hweight8(old_cdclk_state->active_pipes) != hweight8(new_cdclk_state->active_pipes); bool cdclk_changed = intel_cdclk_changed(&old_cdclk_state->actual, @@ -3241,7 +3224,7 @@ static bool intel_cdclk_need_serialize(struct intel_display *display, * We need to poke hw for gen >= 12, because we notify PCode if * pipe power well count changes. */ - return cdclk_changed || (IS_DG2(i915) && power_well_cnt_changed); + return cdclk_changed || (display->platform.dg2 && power_well_cnt_changed); } int intel_modeset_calc_cdclk(struct intel_atomic_state *state) @@ -3376,11 +3359,9 @@ static int intel_compute_max_dotclk(struct intel_display *display) */ void intel_update_max_cdclk(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - if (DISPLAY_VER(display) >= 30) { display->cdclk.max_cdclk_freq = 691200; - } else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { + } else if (display->platform.jasperlake || display->platform.elkhartlake) { if (display->cdclk.hw.ref == 24000) display->cdclk.max_cdclk_freq = 552000; else @@ -3390,9 +3371,9 @@ void intel_update_max_cdclk(struct intel_display *display) display->cdclk.max_cdclk_freq = 648000; else display->cdclk.max_cdclk_freq = 652800; - } else if (IS_GEMINILAKE(dev_priv)) { + } else if (display->platform.geminilake) { display->cdclk.max_cdclk_freq = 316800; - } else if (IS_BROXTON(dev_priv)) { + } else if (display->platform.broxton) { display->cdclk.max_cdclk_freq = 624000; } else if (DISPLAY_VER(display) == 9) { u32 limit = intel_de_read(display, SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; @@ -3416,7 +3397,7 @@ void intel_update_max_cdclk(struct intel_display *display) max_cdclk = 308571; display->cdclk.max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco); - } else if (IS_BROADWELL(dev_priv)) { + } else if (display->platform.broadwell) { /* * FIXME with extra cooling we can allow * 540 MHz for ULX and 675 Mhz for ULT. @@ -3425,15 +3406,15 @@ void intel_update_max_cdclk(struct intel_display *display) */ if (intel_de_read(display, FUSE_STRAP) & HSW_CDCLK_LIMIT) display->cdclk.max_cdclk_freq = 450000; - else if (IS_BROADWELL_ULX(dev_priv)) + else if (display->platform.broadwell_ulx) display->cdclk.max_cdclk_freq = 450000; - else if (IS_BROADWELL_ULT(dev_priv)) + else if (display->platform.broadwell_ult) display->cdclk.max_cdclk_freq = 540000; else display->cdclk.max_cdclk_freq = 675000; - } else if (IS_CHERRYVIEW(dev_priv)) { + } else if (display->platform.cherryview) { display->cdclk.max_cdclk_freq = 320000; - } else if (IS_VALLEYVIEW(dev_priv)) { + } else if (display->platform.valleyview) { display->cdclk.max_cdclk_freq = 400000; } else { /* otherwise assume cdclk is fixed */ @@ -3457,8 +3438,6 @@ void intel_update_max_cdclk(struct intel_display *display) */ void intel_update_cdclk(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - intel_cdclk_get_cdclk(display, &display->cdclk.hw); /* @@ -3467,7 +3446,7 @@ void intel_update_cdclk(struct intel_display *display) * of cdclk that generates 4MHz reference clock freq which is used to * generate GMBus clock. This will vary with the cdclk freq. */ - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + if (display->platform.valleyview || display->platform.cherryview) intel_de_write(display, GMBUSFREQ_VLV, DIV_ROUND_UP(display->cdclk.hw.cdclk, 1000)); } @@ -3561,7 +3540,7 @@ u32 intel_read_rawclk(struct intel_display *display) freq = cnp_rawclk(display); else if (HAS_PCH_SPLIT(dev_priv)) freq = pch_rawclk(display); - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + else if (display->platform.valleyview || display->platform.cherryview) freq = vlv_hrawclk(display); else if (DISPLAY_VER(display) >= 3) freq = i9xx_hrawclk(display); @@ -3742,8 +3721,6 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = { */ void intel_init_cdclk_hooks(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - if (DISPLAY_VER(display) >= 30) { display->funcs.cdclk = &xe3lpd_cdclk_funcs; display->cdclk.table = xe3lpd_cdclk_table; @@ -3756,80 +3733,80 @@ void intel_init_cdclk_hooks(struct intel_display *display) } else if (DISPLAY_VER(display) >= 14) { display->funcs.cdclk = &rplu_cdclk_funcs; display->cdclk.table = mtl_cdclk_table; - } else if (IS_DG2(dev_priv)) { + } else if (display->platform.dg2) { display->funcs.cdclk = &tgl_cdclk_funcs; display->cdclk.table = dg2_cdclk_table; - } else if (IS_ALDERLAKE_P(dev_priv)) { + } else if (display->platform.alderlake_p) { /* Wa_22011320316:adl-p[a0] */ - if (IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { + if (display->platform.alderlake_p && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0)) { display->cdclk.table = adlp_a_step_cdclk_table; display->funcs.cdclk = &tgl_cdclk_funcs; - } else if (IS_RAPTORLAKE_U(dev_priv)) { + } else if (display->platform.alderlake_p_raptorlake_u) { display->cdclk.table = rplu_cdclk_table; display->funcs.cdclk = &rplu_cdclk_funcs; } else { display->cdclk.table = adlp_cdclk_table; display->funcs.cdclk = &tgl_cdclk_funcs; } - } else if (IS_ROCKETLAKE(dev_priv)) { + } else if (display->platform.rocketlake) { display->funcs.cdclk = &tgl_cdclk_funcs; display->cdclk.table = rkl_cdclk_table; } else if (DISPLAY_VER(display) >= 12) { display->funcs.cdclk = &tgl_cdclk_funcs; display->cdclk.table = icl_cdclk_table; - } else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { + } else if (display->platform.jasperlake || display->platform.elkhartlake) { display->funcs.cdclk = &ehl_cdclk_funcs; display->cdclk.table = icl_cdclk_table; } else if (DISPLAY_VER(display) >= 11) { display->funcs.cdclk = &icl_cdclk_funcs; display->cdclk.table = icl_cdclk_table; - } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { + } else if (display->platform.geminilake || display->platform.broxton) { display->funcs.cdclk = &bxt_cdclk_funcs; - if (IS_GEMINILAKE(dev_priv)) + if (display->platform.geminilake) display->cdclk.table = glk_cdclk_table; else display->cdclk.table = bxt_cdclk_table; } else if (DISPLAY_VER(display) == 9) { display->funcs.cdclk = &skl_cdclk_funcs; - } else if (IS_BROADWELL(dev_priv)) { + } else if (display->platform.broadwell) { display->funcs.cdclk = &bdw_cdclk_funcs; - } else if (IS_HASWELL(dev_priv)) { + } else if (display->platform.haswell) { display->funcs.cdclk = &hsw_cdclk_funcs; - } else if (IS_CHERRYVIEW(dev_priv)) { + } else if (display->platform.cherryview) { display->funcs.cdclk = &chv_cdclk_funcs; - } else if (IS_VALLEYVIEW(dev_priv)) { + } else if (display->platform.valleyview) { display->funcs.cdclk = &vlv_cdclk_funcs; - } else if (IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) { + } else if (display->platform.sandybridge || display->platform.ivybridge) { display->funcs.cdclk = &fixed_400mhz_cdclk_funcs; - } else if (IS_IRONLAKE(dev_priv)) { + } else if (display->platform.ironlake) { display->funcs.cdclk = &ilk_cdclk_funcs; - } else if (IS_GM45(dev_priv)) { + } else if (display->platform.gm45) { display->funcs.cdclk = &gm45_cdclk_funcs; - } else if (IS_G45(dev_priv)) { + } else if (display->platform.g45) { display->funcs.cdclk = &g33_cdclk_funcs; - } else if (IS_I965GM(dev_priv)) { + } else if (display->platform.i965gm) { display->funcs.cdclk = &i965gm_cdclk_funcs; - } else if (IS_I965G(dev_priv)) { + } else if (display->platform.i965g) { display->funcs.cdclk = &fixed_400mhz_cdclk_funcs; - } else if (IS_PINEVIEW(dev_priv)) { + } else if (display->platform.pineview) { display->funcs.cdclk = &pnv_cdclk_funcs; - } else if (IS_G33(dev_priv)) { + } else if (display->platform.g33) { display->funcs.cdclk = &g33_cdclk_funcs; - } else if (IS_I945GM(dev_priv)) { + } else if (display->platform.i945gm) { display->funcs.cdclk = &i945gm_cdclk_funcs; - } else if (IS_I945G(dev_priv)) { + } else if (display->platform.i945g) { display->funcs.cdclk = &fixed_400mhz_cdclk_funcs; - } else if (IS_I915GM(dev_priv)) { + } else if (display->platform.i915gm) { display->funcs.cdclk = &i915gm_cdclk_funcs; - } else if (IS_I915G(dev_priv)) { + } else if (display->platform.i915g) { display->funcs.cdclk = &i915g_cdclk_funcs; - } else if (IS_I865G(dev_priv)) { + } else if (display->platform.i865g) { display->funcs.cdclk = &i865g_cdclk_funcs; - } else if (IS_I85X(dev_priv)) { + } else if (display->platform.i85x) { display->funcs.cdclk = &i85x_cdclk_funcs; - } else if (IS_I845G(dev_priv)) { + } else if (display->platform.i845g) { display->funcs.cdclk = &i845g_cdclk_funcs; - } else if (IS_I830(dev_priv)) { + } else if (display->platform.i830) { display->funcs.cdclk = &i830_cdclk_funcs; } -- cgit v1.2.3-59-g8ed1b From 76a677c51097057365564c7ac775ed6c1f117a86 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:42:28 +0200 Subject: drm/i915/cx0: convert to struct intel_display based platform checks Switch the IS_() checks to display->platform., and drop a number of struct drm_i915_private pointers in the process. Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250204134228.2934744-3-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 48b0b9755b2b..0ff76ef10d4b 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -34,13 +34,13 @@ bool intel_encoder_is_c10phy(struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); - if (IS_PANTHERLAKE(i915) && phy == PHY_A) + if (display->platform.pantherlake && phy == PHY_A) return true; - if ((IS_LUNARLAKE(i915) || IS_METEORLAKE(i915)) && phy < PHY_C) + if ((display->platform.lunarlake || display->platform.meteorlake) && phy < PHY_C) return true; return false; @@ -3216,12 +3216,11 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder, static u8 cx0_power_control_disable_val(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *i915 = to_i915(encoder->base.dev); if (intel_encoder_is_c10phy(encoder)) return CX0_P2PG_STATE_DISABLE; - if ((IS_BATTLEMAGE(i915) && encoder->port == PORT_A) || + if ((display->platform.battlemage && encoder->port == PORT_A) || (DISPLAY_VER(display) >= 30 && encoder->type == INTEL_OUTPUT_EDP)) return CX0_P2PG_STATE_DISABLE; -- cgit v1.2.3-59-g8ed1b From d0fcbf81fc798d47c2a62d246a4786d11d050310 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 15:24:23 +0200 Subject: drm/i915/backlight: convert to use struct intel_display Going forward, struct intel_display will be the main display data structure. Convert as much as possible of backlight code to use it. There are some stragglers mainly around PCH checks. Reviewed-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/20250204132423.2910978-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_backlight.c | 494 +++++++++++++------------ 1 file changed, 260 insertions(+), 234 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 7e6ce905bdaf..477b21af71a4 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -104,20 +104,20 @@ u32 intel_backlight_invert_pwm_level(struct intel_connector *connector, u32 val) void intel_backlight_set_pwm_level(const struct drm_connector_state *conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] set backlight PWM = %d\n", + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] set backlight PWM = %d\n", connector->base.base.id, connector->base.name, val); panel->backlight.pwm_funcs->set(conn_state, val); } u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 val) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - drm_WARN_ON_ONCE(&i915->drm, + drm_WARN_ON_ONCE(display->drm, panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0); val = scale(val, panel->backlight.min, panel->backlight.max, @@ -145,32 +145,33 @@ u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val) static u32 lpt_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); - return intel_de_read(i915, BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(display, BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 pch_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); - return intel_de_read(i915, BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(display, BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 i9xx_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 val; - val = intel_de_read(i915, BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (DISPLAY_VER(i915) < 4) + val = intel_de_read(display, BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + if (DISPLAY_VER(display) < 4) val >>= 1; if (panel->backlight.combination_mode) { + struct pci_dev *pdev = to_pci_dev(display->drm->dev); u8 lbpc; - pci_read_config_byte(to_pci_dev(i915->drm.dev), LBPC, &lbpc); + pci_read_config_byte(pdev, LBPC, &lbpc); val *= lbpc; } @@ -179,20 +180,20 @@ static u32 i9xx_get_backlight(struct intel_connector *connector, enum pipe unuse static u32 vlv_get_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); - if (drm_WARN_ON(&i915->drm, pipe != PIPE_A && pipe != PIPE_B)) + if (drm_WARN_ON(display->drm, pipe != PIPE_A && pipe != PIPE_B)) return 0; - return intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(display, VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 bxt_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - return intel_de_read(i915, BXT_BLC_PWM_DUTY(panel->backlight.controller)); + return intel_de_read(display, BXT_BLC_PWM_DUTY(panel->backlight.controller)); } static u32 ext_pwm_get_backlight(struct intel_connector *connector, enum pipe unused) @@ -207,69 +208,70 @@ static u32 ext_pwm_get_backlight(struct intel_connector *connector, enum pipe un static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); u32 val; - val = intel_de_read(i915, BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(i915, BLC_PWM_PCH_CTL2, val | level); + val = intel_de_read(display, BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(display, BLC_PWM_PCH_CTL2, val | level); } static void pch_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); u32 tmp; - tmp = intel_de_read(i915, BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(i915, BLC_PWM_CPU_CTL, tmp | level); + tmp = intel_de_read(display, BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(display, BLC_PWM_CPU_CTL, tmp | level); } static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 tmp, mask; - drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(display->drm, panel->backlight.pwm_level_max == 0); if (panel->backlight.combination_mode) { + struct pci_dev *pdev = to_pci_dev(display->drm->dev); u8 lbpc; lbpc = level * 0xfe / panel->backlight.pwm_level_max + 1; level /= lbpc; - pci_write_config_byte(to_pci_dev(i915->drm.dev), LBPC, lbpc); + pci_write_config_byte(pdev, LBPC, lbpc); } - if (DISPLAY_VER(i915) == 4) { + if (DISPLAY_VER(display) == 4) { mask = BACKLIGHT_DUTY_CYCLE_MASK; } else { level <<= 1; mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; } - tmp = intel_de_read(i915, BLC_PWM_CTL) & ~mask; - intel_de_write(i915, BLC_PWM_CTL, tmp | level); + tmp = intel_de_read(display, BLC_PWM_CTL) & ~mask; + intel_de_write(display, BLC_PWM_CTL, tmp | level); } static void vlv_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe; u32 tmp; - tmp = intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(i915, VLV_BLC_PWM_CTL(pipe), tmp | level); + tmp = intel_de_read(display, VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(display, VLV_BLC_PWM_CTL(pipe), tmp | level); } static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - intel_de_write(i915, BXT_BLC_PWM_DUTY(panel->backlight.controller), level); + intel_de_write(display, BXT_BLC_PWM_DUTY(panel->backlight.controller), level); } static void ext_pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level) @@ -284,10 +286,10 @@ static void intel_panel_actually_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] set backlight level = %d\n", + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] set backlight level = %d\n", connector->base.base.id, connector->base.name, level); panel->backlight.funcs->set(conn_state, level); @@ -300,7 +302,7 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, u32 user_level, u32 user_max) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 hw_level; @@ -313,9 +315,9 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, if (!panel->backlight.present || !conn_state->crtc) return; - mutex_lock(&i915->display.backlight.lock); + mutex_lock(&display->backlight.lock); - drm_WARN_ON(&i915->drm, panel->backlight.max == 0); + drm_WARN_ON(display->drm, panel->backlight.max == 0); hw_level = clamp_user_to_hw(connector, user_level, user_max); panel->backlight.level = hw_level; @@ -329,13 +331,13 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, if (panel->backlight.enabled) intel_panel_actually_set_backlight(conn_state, hw_level); - mutex_unlock(&i915->display.backlight.lock); + mutex_unlock(&display->backlight.lock); } static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); u32 tmp; intel_backlight_set_pwm_level(old_conn_state, level); @@ -348,26 +350,26 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta * This needs rework if we need to add support for CPU PWM on PCH split * platforms. */ - tmp = intel_de_read(i915, BLC_PWM_CPU_CTL2); + tmp = intel_de_read(display, BLC_PWM_CPU_CTL2); if (tmp & BLM_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] CPU backlight was enabled, disabling\n", + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] CPU backlight was enabled, disabling\n", connector->base.base.id, connector->base.name); - intel_de_write(i915, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); + intel_de_write(display, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); } - intel_de_rmw(i915, BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE, 0); + intel_de_rmw(display, BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE, 0); } static void pch_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); intel_backlight_set_pwm_level(old_conn_state, val); - intel_de_rmw(i915, BLC_PWM_CPU_CTL2, BLM_PWM_ENABLE, 0); + intel_de_rmw(display, BLC_PWM_CPU_CTL2, BLM_PWM_ENABLE, 0); - intel_de_rmw(i915, BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE, 0); + intel_de_rmw(display, BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE, 0); } static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) @@ -377,48 +379,49 @@ static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_st static void i965_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { - struct drm_i915_private *i915 = to_i915(old_conn_state->connector->dev); + struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct intel_display *display = to_intel_display(connector); intel_backlight_set_pwm_level(old_conn_state, val); - intel_de_rmw(i915, BLC_PWM_CTL2, BLM_PWM_ENABLE, 0); + intel_de_rmw(display, BLC_PWM_CTL2, BLM_PWM_ENABLE, 0); } static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); enum pipe pipe = to_intel_crtc(old_conn_state->crtc)->pipe; intel_backlight_set_pwm_level(old_conn_state, val); - intel_de_rmw(i915, VLV_BLC_PWM_CTL2(pipe), BLM_PWM_ENABLE, 0); + intel_de_rmw(display, VLV_BLC_PWM_CTL2(pipe), BLM_PWM_ENABLE, 0); } static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; intel_backlight_set_pwm_level(old_conn_state, val); - intel_de_rmw(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_rmw(display, BXT_BLC_PWM_CTL(panel->backlight.controller), BXT_BLC_PWM_ENABLE, 0); if (panel->backlight.controller == 1) - intel_de_rmw(i915, UTIL_PIN_CTL, UTIL_PIN_ENABLE, 0); + intel_de_rmw(display, UTIL_PIN_CTL, UTIL_PIN_ENABLE, 0); } static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; intel_backlight_set_pwm_level(old_conn_state, val); - intel_de_rmw(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_rmw(display, BXT_BLC_PWM_CTL(panel->backlight.controller), BXT_BLC_PWM_ENABLE, 0); } @@ -436,7 +439,7 @@ static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn void intel_backlight_disable(const struct drm_connector_state *old_conn_state) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; if (!panel->backlight.present) @@ -448,49 +451,51 @@ void intel_backlight_disable(const struct drm_connector_state *old_conn_state) * backlight. This will leave the backlight on unnecessarily when * another client is not activated. */ - if (i915->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Skipping backlight disable on vga switch\n", + if (display->drm->switch_power_state == DRM_SWITCH_POWER_CHANGING) { + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Skipping backlight disable on vga switch\n", connector->base.base.id, connector->base.name); return; } - mutex_lock(&i915->display.backlight.lock); + mutex_lock(&display->backlight.lock); if (panel->backlight.device) panel->backlight.device->props.power = BACKLIGHT_POWER_OFF; panel->backlight.enabled = false; panel->backlight.funcs->disable(old_conn_state, 0); - mutex_unlock(&i915->display.backlight.lock); + mutex_unlock(&display->backlight.lock); } static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_display *display = to_intel_display(connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pch_ctl1, pch_ctl2; - pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] PCH backlight already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] PCH backlight already enabled\n", connector->base.base.id, connector->base.name); pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; - intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1); } if (HAS_PCH_LPT(i915)) - intel_de_rmw(i915, SOUTH_CHICKEN2, LPT_PWM_GRANULARITY, + intel_de_rmw(display, SOUTH_CHICKEN2, LPT_PWM_GRANULARITY, panel->backlight.alternate_pwm_increment ? LPT_PWM_GRANULARITY : 0); else - intel_de_rmw(i915, SOUTH_CHICKEN1, SPT_PWM_GRANULARITY, + intel_de_rmw(display, SOUTH_CHICKEN1, SPT_PWM_GRANULARITY, panel->backlight.alternate_pwm_increment ? SPT_PWM_GRANULARITY : 0); pch_ctl2 = panel->backlight.pwm_level_max << 16; - intel_de_write(i915, BLC_PWM_PCH_CTL2, pch_ctl2); + intel_de_write(display, BLC_PWM_PCH_CTL2, pch_ctl2); pch_ctl1 = 0; if (panel->backlight.active_low_pwm) @@ -500,9 +505,9 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state, if (HAS_PCH_LPT(i915)) pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; - intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); - intel_de_posting_read(i915, BLC_PWM_PCH_CTL1); - intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); + intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_posting_read(display, BLC_PWM_PCH_CTL1); + intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); /* This won't stick until the above enable. */ intel_backlight_set_pwm_level(conn_state, level); @@ -512,63 +517,66 @@ static void pch_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 cpu_ctl2, pch_ctl1, pch_ctl2; - cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(display, BLC_PWM_CPU_CTL2); if (cpu_ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] CPU backlight already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] CPU backlight already enabled\n", connector->base.base.id, connector->base.name); cpu_ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2); + intel_de_write(display, BLC_PWM_CPU_CTL2, cpu_ctl2); } - pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] PCH backlight already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] PCH backlight already enabled\n", connector->base.base.id, connector->base.name); pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; - intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1); } if (cpu_transcoder == TRANSCODER_EDP) cpu_ctl2 = BLM_TRANSCODER_EDP; else cpu_ctl2 = BLM_PIPE(cpu_transcoder); - intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2); - intel_de_posting_read(i915, BLC_PWM_CPU_CTL2); - intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); + intel_de_write(display, BLC_PWM_CPU_CTL2, cpu_ctl2); + intel_de_posting_read(display, BLC_PWM_CPU_CTL2); + intel_de_write(display, BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); /* This won't stick until the above enable. */ intel_backlight_set_pwm_level(conn_state, level); pch_ctl2 = panel->backlight.pwm_level_max << 16; - intel_de_write(i915, BLC_PWM_PCH_CTL2, pch_ctl2); + intel_de_write(display, BLC_PWM_PCH_CTL2, pch_ctl2); pch_ctl1 = 0; if (panel->backlight.active_low_pwm) pch_ctl1 |= BLM_PCH_POLARITY; - intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); - intel_de_posting_read(i915, BLC_PWM_PCH_CTL1); - intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); + intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_posting_read(display, BLC_PWM_PCH_CTL1); + intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); } static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 ctl, freq; - ctl = intel_de_read(i915, BLC_PWM_CTL); + ctl = intel_de_read(display, BLC_PWM_CTL); if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] backlight already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] backlight already enabled\n", connector->base.base.id, connector->base.name); - intel_de_write(i915, BLC_PWM_CTL, 0); + intel_de_write(display, BLC_PWM_CTL, 0); } freq = panel->backlight.pwm_level_max; @@ -578,11 +586,11 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, ctl = freq << 17; if (panel->backlight.combination_mode) ctl |= BLM_LEGACY_MODE; - if (IS_PINEVIEW(i915) && panel->backlight.active_low_pwm) + if (display->platform.pineview && panel->backlight.active_low_pwm) ctl |= BLM_POLARITY_PNV; - intel_de_write(i915, BLC_PWM_CTL, ctl); - intel_de_posting_read(i915, BLC_PWM_CTL); + intel_de_write(display, BLC_PWM_CTL, ctl); + intel_de_posting_read(display, BLC_PWM_CTL); /* XXX: combine this into above write? */ intel_backlight_set_pwm_level(conn_state, level); @@ -592,25 +600,26 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2 * that has backlight. */ - if (DISPLAY_VER(i915) == 2) - intel_de_write(i915, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); + if (DISPLAY_VER(display) == 2) + intel_de_write(display, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); } static void i965_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe; u32 ctl, ctl2, freq; - ctl2 = intel_de_read(i915, BLC_PWM_CTL2); + ctl2 = intel_de_read(display, BLC_PWM_CTL2); if (ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] backlight already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] backlight already enabled\n", connector->base.base.id, connector->base.name); ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(i915, BLC_PWM_CTL2, ctl2); + intel_de_write(display, BLC_PWM_CTL2, ctl2); } freq = panel->backlight.pwm_level_max; @@ -618,16 +627,16 @@ static void i965_enable_backlight(const struct intel_crtc_state *crtc_state, freq /= 0xff; ctl = freq << 16; - intel_de_write(i915, BLC_PWM_CTL, ctl); + intel_de_write(display, BLC_PWM_CTL, ctl); ctl2 = BLM_PIPE(pipe); if (panel->backlight.combination_mode) ctl2 |= BLM_COMBINATION_MODE; if (panel->backlight.active_low_pwm) ctl2 |= BLM_POLARITY_I965; - intel_de_write(i915, BLC_PWM_CTL2, ctl2); - intel_de_posting_read(i915, BLC_PWM_CTL2); - intel_de_write(i915, BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); + intel_de_write(display, BLC_PWM_CTL2, ctl2); + intel_de_posting_read(display, BLC_PWM_CTL2); + intel_de_write(display, BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); intel_backlight_set_pwm_level(conn_state, level); } @@ -636,21 +645,22 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 ctl, ctl2; - ctl2 = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); + ctl2 = intel_de_read(display, VLV_BLC_PWM_CTL2(pipe)); if (ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] backlight already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] backlight already enabled\n", connector->base.base.id, connector->base.name); ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2); + intel_de_write(display, VLV_BLC_PWM_CTL2(pipe), ctl2); } ctl = panel->backlight.pwm_level_max << 16; - intel_de_write(i915, VLV_BLC_PWM_CTL(pipe), ctl); + intel_de_write(display, VLV_BLC_PWM_CTL(pipe), ctl); /* XXX: combine this into above write? */ intel_backlight_set_pwm_level(conn_state, level); @@ -658,47 +668,49 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, ctl2 = 0; if (panel->backlight.active_low_pwm) ctl2 |= BLM_POLARITY_I965; - intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2); - intel_de_posting_read(i915, VLV_BLC_PWM_CTL2(pipe)); - intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); + intel_de_write(display, VLV_BLC_PWM_CTL2(pipe), ctl2); + intel_de_posting_read(display, VLV_BLC_PWM_CTL2(pipe)); + intel_de_write(display, VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); } static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 pwm_ctl, val; /* Controller 1 uses the utility pin. */ if (panel->backlight.controller == 1) { - val = intel_de_read(i915, UTIL_PIN_CTL); + val = intel_de_read(display, UTIL_PIN_CTL); if (val & UTIL_PIN_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] utility pin already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] utility pin already enabled\n", connector->base.base.id, connector->base.name); val &= ~UTIL_PIN_ENABLE; - intel_de_write(i915, UTIL_PIN_CTL, val); + intel_de_write(display, UTIL_PIN_CTL, val); } val = 0; if (panel->backlight.util_pin_active_low) val |= UTIL_PIN_POLARITY; - intel_de_write(i915, UTIL_PIN_CTL, + intel_de_write(display, UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) | UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE); } - pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + pwm_ctl = intel_de_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller)); if (pwm_ctl & BXT_BLC_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] backlight already enabled\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] backlight already enabled\n", connector->base.base.id, connector->base.name); pwm_ctl &= ~BXT_BLC_PWM_ENABLE; - intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); } - intel_de_write(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller), + intel_de_write(display, BXT_BLC_PWM_FREQ(panel->backlight.controller), panel->backlight.pwm_level_max); intel_backlight_set_pwm_level(conn_state, level); @@ -707,9 +719,9 @@ static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, if (panel->backlight.active_low_pwm) pwm_ctl |= BXT_BLC_PWM_POLARITY; - intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); - intel_de_posting_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); + intel_de_posting_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl | BXT_BLC_PWM_ENABLE); } @@ -717,19 +729,19 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 pwm_ctl; - pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + pwm_ctl = intel_de_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller)); if (pwm_ctl & BXT_BLC_PWM_ENABLE) { - drm_dbg_kms(&i915->drm, "backlight already enabled\n"); + drm_dbg_kms(display->drm, "backlight already enabled\n"); pwm_ctl &= ~BXT_BLC_PWM_ENABLE; - intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); } - intel_de_write(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller), + intel_de_write(display, BXT_BLC_PWM_FREQ(panel->backlight.controller), panel->backlight.pwm_level_max); intel_backlight_set_pwm_level(conn_state, level); @@ -738,9 +750,9 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state, if (panel->backlight.active_low_pwm) pwm_ctl |= BXT_BLC_PWM_POLARITY; - intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); - intel_de_posting_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); + intel_de_posting_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl | BXT_BLC_PWM_ENABLE); } @@ -782,37 +794,37 @@ void intel_backlight_enable(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; if (!panel->backlight.present) return; - drm_dbg_kms(&i915->drm, "pipe %c\n", pipe_name(pipe)); + drm_dbg_kms(display->drm, "pipe %c\n", pipe_name(pipe)); - mutex_lock(&i915->display.backlight.lock); + mutex_lock(&display->backlight.lock); __intel_backlight_enable(crtc_state, conn_state); - mutex_unlock(&i915->display.backlight.lock); + mutex_unlock(&display->backlight.lock); } #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) static u32 intel_panel_get_backlight(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 val = 0; - mutex_lock(&i915->display.backlight.lock); + mutex_lock(&display->backlight.lock); if (panel->backlight.enabled) val = panel->backlight.funcs->get(connector, intel_connector_get_pipe(connector)); - mutex_unlock(&i915->display.backlight.lock); + mutex_unlock(&display->backlight.lock); - drm_dbg_kms(&i915->drm, "get backlight PWM = %d\n", val); + drm_dbg_kms(display->drm, "get backlight PWM = %d\n", val); return val; } @@ -831,16 +843,16 @@ static void intel_panel_set_backlight(const struct drm_connector_state *conn_sta u32 user_level, u32 user_max) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 hw_level; if (!panel->backlight.present) return; - mutex_lock(&i915->display.backlight.lock); + mutex_lock(&display->backlight.lock); - drm_WARN_ON(&i915->drm, panel->backlight.max == 0); + drm_WARN_ON(display->drm, panel->backlight.max == 0); hw_level = scale_user_to_hw(connector, user_level, user_max); panel->backlight.level = hw_level; @@ -848,18 +860,18 @@ static void intel_panel_set_backlight(const struct drm_connector_state *conn_sta if (panel->backlight.enabled) intel_panel_actually_set_backlight(conn_state, hw_level); - mutex_unlock(&i915->display.backlight.lock); + mutex_unlock(&display->backlight.lock); } static int intel_backlight_device_update_status(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL); + drm_modeset_lock(&display->drm->mode_config.connection_mutex, NULL); - drm_dbg_kms(&i915->drm, "updating intel_backlight, brightness=%d/%d\n", + drm_dbg_kms(display->drm, "updating intel_backlight, brightness=%d/%d\n", bd->props.brightness, bd->props.max_brightness); intel_panel_set_backlight(connector->base.state, bd->props.brightness, bd->props.max_brightness); @@ -880,7 +892,7 @@ static int intel_backlight_device_update_status(struct backlight_device *bd) bd->props.power = BACKLIGHT_POWER_OFF; } - drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + drm_modeset_unlock(&display->drm->mode_config.connection_mutex); return 0; } @@ -888,6 +900,7 @@ static int intel_backlight_device_update_status(struct backlight_device *bd) static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); + struct intel_display *display = to_intel_display(connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); intel_wakeref_t wakeref; int ret = 0; @@ -895,13 +908,13 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd) with_intel_runtime_pm(&i915->runtime_pm, wakeref) { u32 hw_level; - drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL); + drm_modeset_lock(&display->drm->mode_config.connection_mutex, NULL); hw_level = intel_panel_get_backlight(connector); ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness); - drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + drm_modeset_unlock(&display->drm->mode_config.connection_mutex); } return ret; @@ -914,7 +927,7 @@ static const struct backlight_ops intel_backlight_device_ops = { int intel_backlight_device_register(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; struct backlight_properties props; struct backlight_device *bd; @@ -930,7 +943,8 @@ int intel_backlight_device_register(struct intel_connector *connector) WARN_ON(panel->backlight.max == 0); if (!acpi_video_backlight_use_native()) { - drm_info(&i915->drm, "Skipping intel_backlight registration\n"); + drm_info(display->drm, + "Skipping intel_backlight registration\n"); return 0; } @@ -967,7 +981,8 @@ int intel_backlight_device_register(struct intel_connector *connector) */ kfree(name); name = kasprintf(GFP_KERNEL, "card%d-%s-backlight", - i915->drm.primary->index, connector->base.name); + display->drm->primary->index, + connector->base.name); if (!name) return -ENOMEM; } @@ -975,7 +990,7 @@ int intel_backlight_device_register(struct intel_connector *connector) &intel_backlight_device_ops, &props); if (IS_ERR(bd)) { - drm_err(&i915->drm, + drm_err(display->drm, "[CONNECTOR:%d:%s] backlight device %s register failed: %ld\n", connector->base.base.id, connector->base.name, name, PTR_ERR(bd)); ret = PTR_ERR(bd); @@ -984,7 +999,7 @@ int intel_backlight_device_register(struct intel_connector *connector) panel->backlight.device = bd; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] backlight device %s registered\n", connector->base.base.id, connector->base.name, name); @@ -1011,9 +1026,9 @@ void intel_backlight_device_unregister(struct intel_connector *connector) */ static u32 cnp_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); - return DIV_ROUND_CLOSEST(KHz(DISPLAY_RUNTIME_INFO(i915)->rawclk_freq), + return DIV_ROUND_CLOSEST(KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq), pwm_freq_hz); } @@ -1073,9 +1088,9 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); - return DIV_ROUND_CLOSEST(KHz(DISPLAY_RUNTIME_INFO(i915)->rawclk_freq), + return DIV_ROUND_CLOSEST(KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq), pwm_freq_hz * 128); } @@ -1089,13 +1104,13 @@ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); int clock; - if (IS_PINEVIEW(i915)) - clock = KHz(DISPLAY_RUNTIME_INFO(i915)->rawclk_freq); + if (display->platform.pineview) + clock = KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq); else - clock = KHz(i915->display.cdclk.hw.cdclk); + clock = KHz(display->cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32); } @@ -1107,13 +1122,13 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); int clock; - if (IS_G4X(i915)) - clock = KHz(DISPLAY_RUNTIME_INFO(i915)->rawclk_freq); + if (display->platform.g4x) + clock = KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq); else - clock = KHz(i915->display.cdclk.hw.cdclk); + clock = KHz(display->cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128); } @@ -1125,17 +1140,17 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); int mul, clock; - if ((intel_de_read(i915, CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { - if (IS_CHERRYVIEW(i915)) + if ((intel_de_read(display, CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { + if (display->platform.cherryview) clock = KHz(19200); else clock = MHz(25); mul = 16; } else { - clock = KHz(DISPLAY_RUNTIME_INFO(i915)->rawclk_freq); + clock = KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq); mul = 128; } @@ -1144,16 +1159,16 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) static u16 get_vbt_pwm_freq(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); u16 pwm_freq_hz = connector->panel.vbt.backlight.pwm_freq_hz; if (pwm_freq_hz) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "VBT defined backlight frequency %u Hz\n", pwm_freq_hz); } else { pwm_freq_hz = 200; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "default backlight frequency %u Hz\n", pwm_freq_hz); } @@ -1163,20 +1178,20 @@ static u16 get_vbt_pwm_freq(struct intel_connector *connector) static u32 get_backlight_max_vbt(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u16 pwm_freq_hz = get_vbt_pwm_freq(connector); u32 pwm; if (!panel->backlight.pwm_funcs->hz_to_pwm) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "backlight frequency conversion not supported\n"); return 0; } pwm = panel->backlight.pwm_funcs->hz_to_pwm(connector, pwm_freq_hz); if (!pwm) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "backlight frequency conversion failed\n"); return 0; } @@ -1189,11 +1204,11 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector) */ static u32 get_backlight_min_vbt(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; int min; - drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(display->drm, panel->backlight.pwm_level_max == 0); /* * XXX: If the vbt value is 255, it makes min equal to max, which leads @@ -1204,7 +1219,7 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) */ min = clamp_t(int, connector->panel.vbt.backlight.min_brightness, 0, 64); if (min != connector->panel.vbt.backlight.min_brightness) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "clamping VBT min backlight %d/255 to %d/255\n", connector->panel.vbt.backlight.min_brightness, min); } @@ -1215,24 +1230,25 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) { + struct intel_display *display = to_intel_display(connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; bool alt, cpu_mode; if (HAS_PCH_LPT(i915)) - alt = intel_de_read(i915, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; + alt = intel_de_read(display, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; else - alt = intel_de_read(i915, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; + alt = intel_de_read(display, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; panel->backlight.alternate_pwm_increment = alt; - pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; - pch_ctl2 = intel_de_read(i915, BLC_PWM_PCH_CTL2); + pch_ctl2 = intel_de_read(display, BLC_PWM_PCH_CTL2); panel->backlight.pwm_level_max = pch_ctl2 >> 16; - cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(display, BLC_PWM_CPU_CTL2); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1251,19 +1267,19 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus if (cpu_mode) { val = pch_get_backlight(connector, unused); - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "CPU backlight register was enabled, switching to PCH override\n"); /* Write converted CPU PWM value to PCH override register */ lpt_set_backlight(connector->base.state, val); - intel_de_write(i915, BLC_PWM_PCH_CTL1, + intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE); - intel_de_write(i915, BLC_PWM_CPU_CTL2, + intel_de_write(display, BLC_PWM_CPU_CTL2, cpu_ctl2 & ~BLM_PWM_ENABLE); } - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using native PCH PWM for backlight control\n", connector->base.base.id, connector->base.name); @@ -1272,14 +1288,14 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 cpu_ctl2, pch_ctl1, pch_ctl2; - pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; - pch_ctl2 = intel_de_read(i915, BLC_PWM_PCH_CTL2); + pch_ctl2 = intel_de_read(display, BLC_PWM_PCH_CTL2); panel->backlight.pwm_level_max = pch_ctl2 >> 16; if (!panel->backlight.pwm_level_max) @@ -1290,11 +1306,11 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.pwm_level_min = get_backlight_min_vbt(connector); - cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(display, BLC_PWM_CPU_CTL2); panel->backlight.pwm_enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && (pch_ctl1 & BLM_PCH_PWM_ENABLE); - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using native PCH PWM for backlight control\n", connector->base.base.id, connector->base.name); @@ -1303,16 +1319,16 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 ctl, val; - ctl = intel_de_read(i915, BLC_PWM_CTL); + ctl = intel_de_read(display, BLC_PWM_CTL); - if (DISPLAY_VER(i915) == 2 || IS_I915GM(i915) || IS_I945GM(i915)) + if (DISPLAY_VER(display) == 2 || display->platform.i915gm || display->platform.i945gm) panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; - if (IS_PINEVIEW(i915)) + if (display->platform.pineview) panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; panel->backlight.pwm_level_max = ctl >> 17; @@ -1336,7 +1352,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu panel->backlight.pwm_enabled = val != 0; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using native PWM for backlight control\n", connector->base.base.id, connector->base.name); @@ -1345,15 +1361,15 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2; - ctl2 = intel_de_read(i915, BLC_PWM_CTL2); + ctl2 = intel_de_read(display, BLC_PWM_CTL2); panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; - ctl = intel_de_read(i915, BLC_PWM_CTL); + ctl = intel_de_read(display, BLC_PWM_CTL); panel->backlight.pwm_level_max = ctl >> 16; if (!panel->backlight.pwm_level_max) @@ -1369,7 +1385,7 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu panel->backlight.pwm_enabled = ctl2 & BLM_PWM_ENABLE; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using native PWM for backlight control\n", connector->base.base.id, connector->base.name); @@ -1378,17 +1394,17 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2; - if (drm_WARN_ON(&i915->drm, pipe != PIPE_A && pipe != PIPE_B)) + if (drm_WARN_ON(display->drm, pipe != PIPE_A && pipe != PIPE_B)) return -ENODEV; - ctl2 = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); + ctl2 = intel_de_read(display, VLV_BLC_PWM_CTL2(pipe)); panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; - ctl = intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)); + ctl = intel_de_read(display, VLV_BLC_PWM_CTL(pipe)); panel->backlight.pwm_level_max = ctl >> 16; if (!panel->backlight.pwm_level_max) @@ -1401,7 +1417,7 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe panel->backlight.pwm_enabled = ctl2 & BLM_PWM_ENABLE; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using native PWM for backlight control (on pipe %c)\n", connector->base.base.id, connector->base.name, pipe_name(pipe)); @@ -1411,25 +1427,25 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe static int bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 pwm_ctl, val; panel->backlight.controller = connector->panel.vbt.backlight.controller; - pwm_ctl = intel_de_read(i915, + pwm_ctl = intel_de_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller)); /* Controller 1 uses the utility pin. */ if (panel->backlight.controller == 1) { - val = intel_de_read(i915, UTIL_PIN_CTL); + val = intel_de_read(display, UTIL_PIN_CTL); panel->backlight.util_pin_active_low = val & UTIL_PIN_POLARITY; } panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; panel->backlight.pwm_level_max = - intel_de_read(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller)); + intel_de_read(display, BXT_BLC_PWM_FREQ(panel->backlight.controller)); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1441,7 +1457,7 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) panel->backlight.pwm_enabled = pwm_ctl & BXT_BLC_PWM_ENABLE; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using native PWM for backlight control (controller=%d)\n", connector->base.base.id, connector->base.name, panel->backlight.controller); @@ -1449,8 +1465,10 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) return 0; } -static int cnp_num_backlight_controllers(struct drm_i915_private *i915) +static int cnp_num_backlight_controllers(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + if (INTEL_PCH_TYPE(i915) >= PCH_MTL) return 2; @@ -1463,15 +1481,17 @@ static int cnp_num_backlight_controllers(struct drm_i915_private *i915) return 1; } -static bool cnp_backlight_controller_is_valid(struct drm_i915_private *i915, int controller) +static bool cnp_backlight_controller_is_valid(struct intel_display *display, int controller) { - if (controller < 0 || controller >= cnp_num_backlight_controllers(i915)) + struct drm_i915_private *i915 = to_i915(display->drm); + + if (controller < 0 || controller >= cnp_num_backlight_controllers(display)) return false; if (controller == 1 && INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_ADP) - return intel_de_read(i915, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT; + return intel_de_read(display, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT; return true; } @@ -1479,7 +1499,7 @@ static bool cnp_backlight_controller_is_valid(struct drm_i915_private *i915, int static int cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; u32 pwm_ctl; @@ -1488,19 +1508,20 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) * controller. ICP+ can have two controllers, depending on pin muxing. */ panel->backlight.controller = connector->panel.vbt.backlight.controller; - if (!cnp_backlight_controller_is_valid(i915, panel->backlight.controller)) { - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Invalid backlight controller %d, assuming 0\n", + if (!cnp_backlight_controller_is_valid(display, panel->backlight.controller)) { + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] Invalid backlight controller %d, assuming 0\n", connector->base.base.id, connector->base.name, panel->backlight.controller); panel->backlight.controller = 0; } - pwm_ctl = intel_de_read(i915, + pwm_ctl = intel_de_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller)); panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; panel->backlight.pwm_level_max = - intel_de_read(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller)); + intel_de_read(display, BXT_BLC_PWM_FREQ(panel->backlight.controller)); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1512,7 +1533,7 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) panel->backlight.pwm_enabled = pwm_ctl & BXT_BLC_PWM_ENABLE; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using native PCH PWM for backlight control (controller=%d)\n", connector->base.base.id, connector->base.name, panel->backlight.controller); @@ -1523,22 +1544,25 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) static int ext_pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; const char *desc; u32 level; /* Get the right PWM chip for DSI backlight according to VBT */ if (connector->panel.vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { - panel->backlight.pwm = pwm_get(i915->drm.dev, "pwm_pmic_backlight"); + panel->backlight.pwm = pwm_get(display->drm->dev, + "pwm_pmic_backlight"); desc = "PMIC"; } else { - panel->backlight.pwm = pwm_get(i915->drm.dev, "pwm_soc_backlight"); + panel->backlight.pwm = pwm_get(display->drm->dev, + "pwm_soc_backlight"); desc = "SoC"; } if (IS_ERR(panel->backlight.pwm)) { - drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to get the %s PWM chip\n", + drm_err(display->drm, + "[CONNECTOR:%d:%s] Failed to get the %s PWM chip\n", connector->base.base.id, connector->base.name, desc); panel->backlight.pwm = NULL; return -ENODEV; @@ -1556,7 +1580,8 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, level = intel_backlight_invert_pwm_level(connector, level); panel->backlight.pwm_enabled = true; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] PWM already enabled at freq %ld, VBT freq %d, level %d\n", + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] PWM already enabled at freq %ld, VBT freq %d, level %d\n", connector->base.base.id, connector->base.name, NSEC_PER_SEC / (unsigned long)panel->backlight.pwm_state.period, get_vbt_pwm_freq(connector), level); @@ -1566,7 +1591,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, NSEC_PER_SEC / get_vbt_pwm_freq(connector); } - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Using %s PWM for backlight control\n", connector->base.base.id, connector->base.name, desc); @@ -1632,17 +1657,17 @@ void intel_backlight_update(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; if (!panel->backlight.present) return; - mutex_lock(&i915->display.backlight.lock); + mutex_lock(&display->backlight.lock); if (!panel->backlight.enabled) __intel_backlight_enable(crtc_state, conn_state); - mutex_unlock(&i915->display.backlight.lock); + mutex_unlock(&display->backlight.lock); } int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) @@ -1793,13 +1818,14 @@ void intel_backlight_init_funcs(struct intel_panel *panel) { struct intel_connector *connector = container_of(panel, struct intel_connector, panel); + struct intel_display *display = to_intel_display(connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI && intel_dsi_dcs_init_backlight_funcs(connector) == 0) return; - if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) { + if (display->platform.geminilake || display->platform.broxton) { panel->backlight.pwm_funcs = &bxt_pwm_funcs; } else if (INTEL_PCH_TYPE(i915) >= PCH_CNP) { panel->backlight.pwm_funcs = &cnp_pwm_funcs; @@ -1810,13 +1836,13 @@ void intel_backlight_init_funcs(struct intel_panel *panel) panel->backlight.pwm_funcs = &spt_pwm_funcs; } else if (HAS_PCH_SPLIT(i915)) { panel->backlight.pwm_funcs = &pch_pwm_funcs; - } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + } else if (display->platform.valleyview || display->platform.cherryview) { if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) { panel->backlight.pwm_funcs = &ext_pwm_funcs; } else { panel->backlight.pwm_funcs = &vlv_pwm_funcs; } - } else if (DISPLAY_VER(i915) == 4) { + } else if (DISPLAY_VER(display) == 4) { panel->backlight.pwm_funcs = &i965_pwm_funcs; } else { panel->backlight.pwm_funcs = &i9xx_pwm_funcs; @@ -1826,7 +1852,7 @@ void intel_backlight_init_funcs(struct intel_panel *panel) if (intel_dp_aux_init_backlight_funcs(connector) == 0) return; - if (!intel_has_quirk(&i915->display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) + if (!intel_has_quirk(display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) connector->panel.backlight.power = intel_pps_backlight_power; } -- cgit v1.2.3-59-g8ed1b From 0e1daf2b32dc85559cb1bb67e91c5a42db332cba Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Wed, 5 Feb 2025 17:47:34 +0800 Subject: drm/edp-panel: Add LG Display panel model LP079QX1-SP0V The raw edid for LP079QX1-SP0V panel model is: 00 ff ff ff ff ff ff 00 16 83 00 00 00 00 00 00 04 17 01 00 a5 10 0c 78 06 ef 05 a3 54 4c 99 26 0f 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ea 4e 00 4c 60 00 14 80 0c 10 84 00 78 a0 00 00 00 18 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe 00 4c 50 30 37 39 51 58 31 2d 53 50 30 56 00 00 00 fc 00 43 6f 6c 6f 72 20 4c 43 44 0a 20 20 20 00 3f Signed-off-by: Damon Ding Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250205094734.562992-1-damon.ding@rock-chips.com --- drivers/gpu/drm/panel/panel-edp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 25bb7e454fc9..13cca7ebf0f7 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1814,6 +1814,14 @@ static const struct panel_delay delay_200_500_e250 = { .enable = 250, }; +static const struct panel_delay delay_50_500_e200_d200_po2e335 = { + .hpd_absent = 50, + .unprepare = 500, + .enable = 200, + .disable = 200, + .powered_on_to_enable = 335, +}; + #define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \ { \ .ident = { \ @@ -1965,6 +1973,8 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'S', 'W', 0x1104, &delay_200_500_e50, "MNB601LS1-4"), EDP_PANEL_ENTRY('C', 'S', 'W', 0x1448, &delay_200_500_e50, "MNE007QS3-7"), + EDP_PANEL_ENTRY('E', 'T', 'C', 0x0000, &delay_50_500_e200_d200_po2e335, "LP079QX1-SP0V"), + EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d51, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5b, &delay_200_500_e200, "MB116AN01"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5c, &delay_200_500_e200, "MB116AN01-2"), -- cgit v1.2.3-59-g8ed1b From 7e3bf00047cdfe2b09e9a0d77b99bedc15406bfa Mon Sep 17 00:00:00 2001 From: Tejas Vipin Date: Sun, 2 Feb 2025 00:24:39 +0530 Subject: drm/panel: sharp-ls060t1sx01: transition to mipi_dsi wrapped functions Changes the sharp-ls060t1sx01 panel to use multi style functions for improved error handling. Signed-off-by: Tejas Vipin Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250201185439.157613-1-tejasvipin76@gmail.com --- drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c | 59 +++++++------------------ 1 file changed, 16 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c index 74c760ee0c2d..0b4e0983639b 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c @@ -44,60 +44,39 @@ static void sharp_ls060_reset(struct sharp_ls060 *ctx) static int sharp_ls060_on(struct sharp_ls060 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x13); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_MEMORY_START); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display on: %d\n", ret); - return ret; - } - msleep(50); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 50); - return 0; + return dsi_ctx.accum_err; } -static int sharp_ls060_off(struct sharp_ls060 *ctx) +static void sharp_ls060_off(struct sharp_ls060 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - usleep_range(2000, 3000); - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(121); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_usleep_range(&dsi_ctx, 2000, 3000); - return 0; + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 121); } static int sharp_ls060_prepare(struct drm_panel *panel) { struct sharp_ls060 *ctx = to_sharp_ls060(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_enable(ctx->vddi_supply); @@ -125,10 +104,8 @@ static int sharp_ls060_prepare(struct drm_panel *panel) sharp_ls060_reset(ctx); ret = sharp_ls060_on(ctx); - if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); + if (ret < 0) goto err_on; - } return 0; @@ -154,12 +131,8 @@ err_avdd: static int sharp_ls060_unprepare(struct drm_panel *panel) { struct sharp_ls060 *ctx = to_sharp_ls060(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = sharp_ls060_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + sharp_ls060_off(ctx); regulator_disable(ctx->vddh_supply); -- cgit v1.2.3-59-g8ed1b From aa0a9861bf5157c51cda8191813d1b52374d5c78 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 4 Feb 2025 16:05:18 +0200 Subject: drm/i915/psr: clarify intel_psr_pre_plane_update() conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the conditions easier to follow. We don't do anything for !psr->enabled, so hoist psr->enabled check higher, avoiding all the checks when !psr->enabled. Stop the bitwise OR abuse on booleans by removing the temporary variable altogether. v2: Rebase Cc: Jouni Högander Cc: Suraj Kandpal Reviewed-by: Jouni Högander # v1 Link: https://patchwork.freedesktop.org/patch/msgid/20250204140518.2971530-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_psr.c | 46 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 2bdb6c9c2283..861e50ceef85 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -2804,34 +2804,30 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, old_crtc_state->uapi.encoder_mask) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_psr *psr = &intel_dp->psr; - bool needs_to_disable = false; mutex_lock(&psr->lock); - /* - * Reasons to disable: - * - PSR disabled in new state - * - All planes will go inactive - * - Changing between PSR versions - * - Region Early Transport changing - * - Display WA #1136: skl, bxt - */ - needs_to_disable |= intel_crtc_needs_modeset(new_crtc_state); - needs_to_disable |= !new_crtc_state->has_psr; - needs_to_disable |= !new_crtc_state->active_planes; - needs_to_disable |= new_crtc_state->has_sel_update != psr->sel_update_enabled; - needs_to_disable |= new_crtc_state->enable_psr2_su_region_et != - psr->su_region_et_enabled; - needs_to_disable |= new_crtc_state->has_panel_replay != - psr->panel_replay_enabled; - needs_to_disable |= DISPLAY_VER(i915) < 11 && - new_crtc_state->wm_level_disabled; - - if (psr->enabled && needs_to_disable) - intel_psr_disable_locked(intel_dp); - else if (psr->enabled && new_crtc_state->wm_level_disabled) - /* Wa_14015648006 */ - wm_optimization_wa(intel_dp, new_crtc_state); + if (psr->enabled) { + /* + * Reasons to disable: + * - PSR disabled in new state + * - All planes will go inactive + * - Changing between PSR versions + * - Region Early Transport changing + * - Display WA #1136: skl, bxt + */ + if (intel_crtc_needs_modeset(new_crtc_state) || + !new_crtc_state->has_psr || + !new_crtc_state->active_planes || + new_crtc_state->has_sel_update != psr->sel_update_enabled || + new_crtc_state->enable_psr2_su_region_et != psr->su_region_et_enabled || + new_crtc_state->has_panel_replay != psr->panel_replay_enabled || + (DISPLAY_VER(i915) < 11 && new_crtc_state->wm_level_disabled)) + intel_psr_disable_locked(intel_dp); + else if (new_crtc_state->wm_level_disabled) + /* Wa_14015648006 */ + wm_optimization_wa(intel_dp, new_crtc_state); + } mutex_unlock(&psr->lock); } -- cgit v1.2.3-59-g8ed1b From 9f40d7a94427a503e303b2a2d8db227d615e32c1 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 4 Feb 2025 14:40:05 +0200 Subject: drm/rockchip: vop2: Drop unnecessary if_pixclk_rate computation The if_pixclk_rate variable is not being used outside of the if-block in rk3588_calc_cru_cfg(), hence move the superfluous assignment from the first branch to the inner comment-block. Signed-off-by: Cristian Ciocaltea Tested-by: FUKAUMI Naoki Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-2-d71c6a196e58@collabora.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 17a98845fd31..2455d4a55abd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1905,8 +1905,8 @@ static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id, K = 2; } - if_pixclk_rate = (dclk_core_rate << 1) / K; /* + * if_pixclk_rate = (dclk_core_rate << 1) / K; * if_dclk_rate = dclk_core_rate / K; * *if_pixclk_div = dclk_rate / if_pixclk_rate; * *if_dclk_div = dclk_rate / if_dclk_rate; -- cgit v1.2.3-59-g8ed1b From 2c1268e7aad0819f38e56134bbc2095fd95fde1b Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 4 Feb 2025 14:40:06 +0200 Subject: drm/rockchip: vop2: Improve display modes handling on RK3588 HDMI0 The RK3588 specific implementation is currently quite limited in terms of handling the full range of display modes supported by the connected screens, e.g. 2560x1440@75Hz, 2048x1152@60Hz, 1024x768@60Hz are just a few of them. Additionally, it doesn't cope well with non-integer refresh rates like 59.94, 29.97, 23.98, etc. Make use of HDMI0 PHY PLL as a more accurate DCLK source to handle all display modes up to 4K@60Hz. Tested-by: FUKAUMI Naoki Signed-off-by: Cristian Ciocaltea Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-3-d71c6a196e58@collabora.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 2455d4a55abd..afc946ead870 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -159,6 +159,7 @@ struct vop2_video_port { struct drm_crtc crtc; struct vop2 *vop2; struct clk *dclk; + struct clk *dclk_src; unsigned int id; const struct vop2_video_port_data *data; @@ -214,6 +215,7 @@ struct vop2 { struct clk *hclk; struct clk *aclk; struct clk *pclk; + struct clk *pll_hdmiphy0; /* optional internal rgb encoder */ struct rockchip_rgb *rgb; @@ -222,6 +224,8 @@ struct vop2 { struct vop2_win win[]; }; +#define VOP2_MAX_DCLK_RATE 600000000 + #define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \ (x) == ROCKCHIP_VOP2_EP_HDMI1) @@ -1155,6 +1159,9 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID); + if (vp->dclk_src) + clk_set_parent(vp->dclk, vp->dclk_src); + clk_disable_unprepare(vp->dclk); vop2->enable_count--; @@ -2259,6 +2266,27 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0); + /* + * Switch to HDMI PHY PLL as DCLK source for display modes up + * to 4K@60Hz, if available, otherwise keep using the system CRU. + */ + if (vop2->pll_hdmiphy0 && clock <= VOP2_MAX_DCLK_RATE) { + drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { + struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); + + if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) { + if (!vp->dclk_src) + vp->dclk_src = clk_get_parent(vp->dclk); + + ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0); + if (ret < 0) + drm_warn(vop2->drm, + "Could not switch to HDMI0 PHY PLL: %d\n", ret); + break; + } + } + } + clk_set_rate(vp->dclk, clock); vop2_post_config(crtc); @@ -3699,6 +3727,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(vop2->pclk); } + vop2->pll_hdmiphy0 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy0"); + if (IS_ERR(vop2->pll_hdmiphy0)) { + drm_err(vop2->drm, "failed to get pll_hdmiphy0\n"); + return PTR_ERR(vop2->pll_hdmiphy0); + } + vop2->irq = platform_get_irq(pdev, 0); if (vop2->irq < 0) { drm_err(vop2->drm, "cannot find irq for vop2\n"); -- cgit v1.2.3-59-g8ed1b From 8d8334632ea62424233ac6529712868241d0f8df Mon Sep 17 00:00:00 2001 From: Krzysztof Karas Date: Thu, 30 Jan 2025 09:19:31 +0000 Subject: drm/i915/selftests: avoid using uninitialized context There is an error path in igt_ppgtt_alloc(), which leads to ww object being passed down to i915_gem_ww_ctx_fini() without initialization. Correct that by only putting ppgtt->vm and returning early. Fixes: 480ae79537b2 ("drm/i915/selftests: Prepare gtt tests for obj->mm.lock removal") Signed-off-by: Krzysztof Karas Reviewed-by: Mikolaj Wasiak Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/iuaonpjc3rywmvhna6umjlvzilocn2uqsrxfxfob24e2taocbi@lkaivvfp4777 --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 5c397a2df70e..5d27e1c733c5 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -168,7 +168,7 @@ static int igt_ppgtt_alloc(void *arg) return PTR_ERR(ppgtt); if (!ppgtt->vm.allocate_va_range) - goto err_ppgtt_cleanup; + goto ppgtt_vm_put; /* * While we only allocate the page tables here and so we could @@ -236,7 +236,7 @@ err_ppgtt_cleanup: goto retry; } i915_gem_ww_ctx_fini(&ww); - +ppgtt_vm_put: i915_vm_put(&ppgtt->vm); return err; } -- cgit v1.2.3-59-g8ed1b From 241d8312131e66f31754659bd49169e1822ac1a8 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 22 Jan 2025 17:17:51 +0200 Subject: drm/i915: Move VT-d alignment into plane->min_alignment() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we don't account for the VT-d alignment w/a in plane->min_alignment() which means that panning inside a larger framebuffer can still cause the plane SURF to be misaligned. Fix the issue by moving the VT-d alignment w/a into plane->min_alignment() itself (for the affected platforms). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250122151755.6928-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_plane.c | 10 ++++++++++ drivers/gpu/drm/i915/display/intel_cursor.c | 5 +++++ drivers/gpu/drm/i915/display/intel_fb_pin.c | 8 -------- drivers/gpu/drm/i915/display/intel_sprite.c | 5 +++++ drivers/gpu/drm/i915/display/skl_universal_plane.c | 4 ++++ 5 files changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index ed171fbf8720..19cc34babef3 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -780,9 +780,14 @@ unsigned int vlv_plane_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) { + struct drm_i915_private *i915 = to_i915(plane->base.dev); + if (intel_plane_can_async_flip(plane, fb->modifier)) return 256 * 1024; + if (intel_scanout_needs_vtd_wa(i915)) + return 256 * 1024; + switch (fb->modifier) { case I915_FORMAT_MOD_X_TILED: return 4 * 1024; @@ -798,9 +803,14 @@ static unsigned int g4x_primary_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) { + struct drm_i915_private *i915 = to_i915(plane->base.dev); + if (intel_plane_can_async_flip(plane, fb->modifier)) return 256 * 1024; + if (intel_scanout_needs_vtd_wa(i915)) + return 256 * 1024; + switch (fb->modifier) { case I915_FORMAT_MOD_X_TILED: case DRM_FORMAT_MOD_LINEAR: diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 48c3d212f690..ed8e65364539 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -372,6 +372,11 @@ static unsigned int i9xx_cursor_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) { + struct drm_i915_private *i915 = to_i915(plane->base.dev); + + if (intel_scanout_needs_vtd_wa(i915)) + return 256 * 1024; + return 4 * 1024; /* physical for i915/i945 */ } diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c index dd3ac7f98dfc..2b9ad46eaef7 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -126,14 +126,6 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, if (drm_WARN_ON(dev, alignment && !is_power_of_2(alignment))) return ERR_PTR(-EINVAL); - /* Note that the w/a also requires 64 PTE of padding following the - * bo. We currently fill all unused PTE with the shadow page and so - * we should always have valid PTE following the scanout preventing - * the VT-d warning. - */ - if (intel_scanout_needs_vtd_wa(dev_priv) && alignment < 256 * 1024) - alignment = 256 * 1024; - /* * Global gtt pte registers are special registers which actually forward * writes to a chunk of system memory. Which means that there is no risk diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 13996d7059ad..d63e71fe469e 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -980,6 +980,11 @@ static unsigned int g4x_sprite_min_alignment(struct intel_plane *plane, const struct drm_framebuffer *fb, int color_plane) { + struct drm_i915_private *i915 = to_i915(plane->base.dev); + + if (intel_scanout_needs_vtd_wa(i915)) + return 256 * 1024; + return 4 * 1024; } diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index ba5db553c374..d4774abbf462 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -645,6 +645,10 @@ static u32 skl_plane_min_alignment(struct intel_plane *plane, if (color_plane != 0) return 4 * 1024; + /* + * VT-d needs at least 256k alignment, + * but that's already covered below. + */ switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: -- cgit v1.2.3-59-g8ed1b From 2ffa4878512d429eecffe4ef786cbf102a8b8165 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 22 Jan 2025 17:17:52 +0200 Subject: drm/i915: Use more optimal VTd alignment for planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depending on the platform and/or plane type we can get away with a bit less alignment in the VT-d w/a. Reduce the numbers accordingly. Note that it's not actually clear in VLV/CHV need this w/a, and if they do we don't actually know what kind of alignment is sufficient. Leave the 256k alignment in place for now, but toss in a FIXME. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250122151755.6928-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_plane.c | 1 + drivers/gpu/drm/i915/display/intel_cursor.c | 2 +- drivers/gpu/drm/i915/display/intel_sprite.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 19cc34babef3..65a2eb9e92c4 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -785,6 +785,7 @@ unsigned int vlv_plane_min_alignment(struct intel_plane *plane, if (intel_plane_can_async_flip(plane, fb->modifier)) return 256 * 1024; + /* FIXME undocumented so not sure what's actually needed */ if (intel_scanout_needs_vtd_wa(i915)) return 256 * 1024; diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index ed8e65364539..cbeea9d96517 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -375,7 +375,7 @@ static unsigned int i9xx_cursor_min_alignment(struct intel_plane *plane, struct drm_i915_private *i915 = to_i915(plane->base.dev); if (intel_scanout_needs_vtd_wa(i915)) - return 256 * 1024; + return 64 * 1024; return 4 * 1024; /* physical for i915/i945 */ } diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index d63e71fe469e..af121c720b89 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -983,7 +983,7 @@ static unsigned int g4x_sprite_min_alignment(struct intel_plane *plane, struct drm_i915_private *i915 = to_i915(plane->base.dev); if (intel_scanout_needs_vtd_wa(i915)) - return 256 * 1024; + return 128 * 1024; return 4 * 1024; } -- cgit v1.2.3-59-g8ed1b From 44a34dec43e8f214913e16204525d7253acc1891 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 22 Jan 2025 17:17:53 +0200 Subject: drm/i915: Calculate the VT-d guard size in the display code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently i915_gem_object_pin_to_display_plane() uses i915_gem_object_get_tile_row_size() to calculate the tile row size for the VT-d guard w/a. That's not really proper since i915_gem_object_get_tile_row_size() only works for fenced BOs, nor does it take rotation into account. Remedy the situation by calculating the VT-d guard size in the display code where we have more information readily available. Although the default guard size (168 PTEs now) should cover the more typical fb size use cases anyway, and only very large Y/Yf-tiled framebuffers might have tile row size that exceeds it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250122151755.6928-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 33 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_fb.h | 3 +++ drivers/gpu/drm/i915/display/intel_fb_pin.c | 12 +++++++++- drivers/gpu/drm/i915/display/intel_fb_pin.h | 1 + drivers/gpu/drm/i915/display/intel_fbdev.c | 2 ++ drivers/gpu/drm/i915/display/intel_overlay.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 15 +++--------- drivers/gpu/drm/i915/gem/i915_gem_object.h | 2 +- drivers/gpu/drm/xe/display/xe_fb_pin.c | 1 + drivers/gpu/drm/xe/display/xe_plane_initial.c | 2 +- 10 files changed, 57 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 9f7f1b9f3275..ea8c8a99c5c7 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1761,6 +1761,39 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * return 0; } +unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb, + const struct intel_fb_view *view, + unsigned int rotation) +{ + struct drm_i915_private *i915 = to_i915(fb->dev); + unsigned int vtd_guard; + int color_plane; + + if (!intel_scanout_needs_vtd_wa(i915)) + return 0; + + vtd_guard = 168; + + for (color_plane = 0; color_plane < fb->format->num_planes; color_plane++) { + unsigned int stride, tile; + + if (intel_fb_is_ccs_aux_plane(fb, color_plane) || + is_gen12_ccs_cc_plane(fb, color_plane)) + continue; + + stride = view->color_plane[color_plane].mapping_stride; + + if (drm_rotation_90_or_270(rotation)) + tile = intel_tile_height(fb, color_plane); + else + tile = intel_tile_width_bytes(fb, color_plane); + + vtd_guard = max(vtd_guard, DIV_ROUND_UP(stride, tile)); + } + + return vtd_guard; +} + static void intel_plane_remap_gtt(struct intel_plane_state *plane_state) { struct drm_i915_private *i915 = diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index d78993e5eb62..026e9f7f98f7 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -83,6 +83,9 @@ bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb); int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb); void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotation, struct intel_fb_view *view); +unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb, + const struct intel_fb_view *view, + unsigned int rotation); int intel_plane_compute_gtt(struct intel_plane_state *plane_state); int intel_framebuffer_init(struct intel_framebuffer *ifb, diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c index 2b9ad46eaef7..204e7e3e48ca 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -107,6 +107,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, const struct i915_gtt_view *view, unsigned int alignment, unsigned int phys_alignment, + unsigned int vtd_guard, bool uses_fence, unsigned long *out_flags) { @@ -162,7 +163,7 @@ retry: goto err; vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment, - view, pinctl); + vtd_guard, view, pinctl); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto err_unpin; @@ -244,6 +245,14 @@ intel_plane_fb_min_phys_alignment(const struct intel_plane_state *plane_state) return plane->min_alignment(plane, fb, 0); } +static unsigned int +intel_plane_fb_vtd_guard(const struct intel_plane_state *plane_state) +{ + return intel_fb_view_vtd_guard(plane_state->hw.fb, + &plane_state->view, + plane_state->hw.rotation); +} + int intel_plane_pin_fb(struct intel_plane_state *plane_state, const struct intel_plane_state *old_plane_state) { @@ -256,6 +265,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, vma = intel_fb_pin_to_ggtt(&fb->base, &plane_state->view.gtt, intel_plane_fb_min_alignment(plane_state), intel_plane_fb_min_phys_alignment(plane_state), + intel_plane_fb_vtd_guard(plane_state), intel_plane_uses_fence(plane_state), &plane_state->flags); if (IS_ERR(vma)) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index 0fc6d9044638..01770dbba2e0 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -18,6 +18,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, const struct i915_gtt_view *view, unsigned int alignment, unsigned int phys_alignment, + unsigned int vtd_guard, bool uses_fence, unsigned long *out_flags); diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 6c0808133397..833cded53d37 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -228,6 +228,8 @@ static int intelfb_create(struct drm_fb_helper *helper, */ vma = intel_fb_pin_to_ggtt(&fb->base, &view, fb->min_alignment, 0, + intel_fb_view_vtd_guard(&fb->base, &fb->normal_view, + DRM_MODE_ROTATE_0), false, &flags); if (IS_ERR(vma)) { ret = PTR_ERR(vma); diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index bbb0db33740e..4d00db86131b 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -778,7 +778,7 @@ static struct i915_vma *intel_overlay_pin_fb(struct drm_i915_gem_object *new_bo) retry: ret = i915_gem_object_lock(new_bo, &ww); if (!ret) { - vma = i915_gem_object_pin_to_display_plane(new_bo, &ww, 0, + vma = i915_gem_object_pin_to_display_plane(new_bo, &ww, 0, 0, NULL, PIN_MAPPABLE); ret = PTR_ERR_OR_ZERO(vma); } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index ee55caca67a1..75a143d996e0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -18,8 +18,6 @@ #include "i915_gem_object_frontbuffer.h" #include "i915_vma.h" -#define VTD_GUARD (168u * I915_GTT_PAGE_SIZE) /* 168 or tile-row PTE padding */ - static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); @@ -424,7 +422,7 @@ out: struct i915_vma * i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, - u32 alignment, + u32 alignment, unsigned int guard, const struct i915_gtt_view *view, unsigned int flags) { @@ -453,15 +451,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, return ERR_PTR(ret); /* VT-d may overfetch before/after the vma, so pad with scratch */ - if (intel_scanout_needs_vtd_wa(i915)) { - unsigned int guard = VTD_GUARD; - - if (i915_gem_object_is_tiled(obj)) - guard = max(guard, - i915_gem_object_get_tile_row_size(obj)); - - flags |= PIN_OFFSET_GUARD | guard; - } + if (guard) + flags |= PIN_OFFSET_GUARD | (guard * I915_GTT_PAGE_SIZE); /* * As the user may map the buffer once pinned in the display plane diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index bb713e096db2..a5f34542135c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -776,7 +776,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write); struct i915_vma * __must_check i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, - u32 alignment, + u32 alignment, unsigned int guard, const struct i915_gtt_view *view, unsigned int flags); diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 25ce032bb293..11a6b996d739 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -369,6 +369,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, const struct i915_gtt_view *view, unsigned int alignment, unsigned int phys_alignment, + unsigned int vtd_guard, bool uses_fence, unsigned long *out_flags) { diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 2a2f250fa495..25c80dd6d386 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -215,7 +215,7 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, plane_state->uapi.rotation, &plane_state->view); vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt, - 0, 0, false, &plane_state->flags); + 0, 0, 0, false, &plane_state->flags); if (IS_ERR(vma)) goto nofb; -- cgit v1.2.3-59-g8ed1b From 4d291c441bbc78805e6a4775383bd5a6f53d2e10 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 22 Jan 2025 17:17:54 +0200 Subject: drm/i915: Use per-plane VT-d guard numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bspec lists different VT-d guard numbers (the number of dummy padding PTEs) for different platforms and plane types. Use those instead of just assuming the max glk+ number for everything. This could avoid a bit of overhead on older platforms due to reduced padding, and it makes it easier to cross check with the spec. Note that VLV/CHV do not document this w/a at all, so not sure if it's actually needed or not. Nor do we actually know how much padding is required if it is needed. For now use the same 128 PTEs that we use for snb-bdw primary planes. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250122151755.6928-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_plane.c | 4 ++++ drivers/gpu/drm/i915/display/intel_cursor.c | 3 +++ drivers/gpu/drm/i915/display/intel_display_types.h | 2 ++ drivers/gpu/drm/i915/display/intel_fb.c | 23 ++++++++++++++++++---- drivers/gpu/drm/i915/display/intel_sprite.c | 10 ++++++++++ drivers/gpu/drm/i915/display/skl_universal_plane.c | 3 +++ 6 files changed, 41 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 65a2eb9e92c4..bd3f8db13700 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -958,6 +958,10 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) else plane->min_alignment = i9xx_plane_min_alignment; + /* FIXME undocumented for VLV/CHV so not sure what's actually needed */ + if (intel_scanout_needs_vtd_wa(dev_priv)) + plane->vtd_guard = 128; + if (IS_I830(dev_priv) || IS_I845G(dev_priv)) { plane->update_arm = i830_plane_update_arm; } else { diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index cbeea9d96517..6a1035a22b0a 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -1019,6 +1019,9 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, else cursor->min_alignment = i9xx_cursor_min_alignment; + if (intel_scanout_needs_vtd_wa(dev_priv)) + cursor->vtd_guard = 2; + cursor->update_arm = i9xx_cursor_update_arm; cursor->disable_arm = i9xx_cursor_disable_arm; cursor->get_hw_state = i9xx_cursor_get_hw_state; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 37b1a216b13b..d8a3d4d6aedf 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -144,6 +144,7 @@ struct intel_framebuffer { struct i915_address_space *dpt_vm; unsigned int min_alignment; + unsigned int vtd_guard; }; enum intel_hotplug_state { @@ -1448,6 +1449,7 @@ struct intel_plane { enum plane_id id; enum pipe pipe; bool need_async_flip_toggle_wa; + u8 vtd_guard; u32 frontbuffer_bit; struct { diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index ea8c8a99c5c7..d9328877cc6d 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1660,6 +1660,22 @@ static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb) return min_alignment; } +static unsigned int intel_fb_vtd_guard(const struct drm_framebuffer *fb) +{ + struct drm_i915_private *i915 = to_i915(fb->dev); + struct intel_plane *plane; + unsigned int vtd_guard = 0; + + for_each_intel_plane(&i915->drm, plane) { + if (!drm_plane_has_format(&plane->base, fb->format->format, fb->modifier)) + continue; + + vtd_guard = max_t(unsigned int, vtd_guard, plane->vtd_guard); + } + + return vtd_guard; +} + int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb) { struct drm_gem_object *obj = intel_fb_bo(&fb->base); @@ -1757,6 +1773,7 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * } fb->min_alignment = intel_fb_min_alignment(&fb->base); + fb->vtd_guard = intel_fb_vtd_guard(&fb->base); return 0; } @@ -1765,15 +1782,13 @@ unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb, const struct intel_fb_view *view, unsigned int rotation) { - struct drm_i915_private *i915 = to_i915(fb->dev); unsigned int vtd_guard; int color_plane; - if (!intel_scanout_needs_vtd_wa(i915)) + vtd_guard = to_intel_framebuffer(fb)->vtd_guard; + if (!vtd_guard) return 0; - vtd_guard = 168; - for (color_plane = 0; color_plane < fb->format->num_planes; color_plane++) { unsigned int stride, tile; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index af121c720b89..a6b27798fdc3 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -1609,6 +1609,10 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->min_alignment = vlv_plane_min_alignment; plane->min_cdclk = vlv_plane_min_cdclk; + /* FIXME undocumented for VLV/CHV so not sure what's actually needed */ + if (intel_scanout_needs_vtd_wa(dev_priv)) + plane->vtd_guard = 128; + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { formats = chv_pipe_b_sprite_formats; num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats); @@ -1635,6 +1639,9 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->min_alignment = g4x_sprite_min_alignment; + if (intel_scanout_needs_vtd_wa(dev_priv)) + plane->vtd_guard = 64; + formats = snb_sprite_formats; num_formats = ARRAY_SIZE(snb_sprite_formats); @@ -1649,6 +1656,9 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->min_alignment = g4x_sprite_min_alignment; plane->min_cdclk = g4x_sprite_min_cdclk; + if (intel_scanout_needs_vtd_wa(dev_priv)) + plane->vtd_guard = 64; + if (IS_SANDYBRIDGE(dev_priv)) { formats = snb_sprite_formats; num_formats = ARRAY_SIZE(snb_sprite_formats); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index d4774abbf462..ee93361bba09 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2750,6 +2750,9 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, else plane->min_alignment = skl_plane_min_alignment; + if (intel_scanout_needs_vtd_wa(dev_priv)) + plane->vtd_guard = DISPLAY_VER(dev_priv) >= 10 ? 168 : 136; + if (DISPLAY_VER(dev_priv) >= 11) { plane->update_noarm = icl_plane_update_noarm; plane->update_arm = icl_plane_update_arm; -- cgit v1.2.3-59-g8ed1b From a5072fc77fb9e38fa9fd883642c83c3720049159 Mon Sep 17 00:00:00 2001 From: Hermes Wu Date: Tue, 21 Jan 2025 15:01:51 +0800 Subject: drm/bridge: it6505: fix HDCP V match check is not performed correctly Fix a typo where V compare incorrectly compares av[] with av[] itself, which can result in HDCP failure. The loop of V compare is expected to iterate for 5 times which compare V array form av[0][] to av[4][]. It should check loop counter reach the last statement "i == 5" before return true Fixes: 0989c02c7a5c ("drm/bridge: it6505: fix HDCP CTS compare V matching") Signed-off-by: Hermes Wu Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250121-fix-hdcp-v-comp-v4-1-185f45c728dc@ite.com.tw --- drivers/gpu/drm/bridge/ite-it6505.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 88ef76a37fe6..76dabca04d0d 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -2250,12 +2250,13 @@ static bool it6505_hdcp_part2_ksvlist_check(struct it6505 *it6505) continue; } - for (i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) if (bv[i][3] != av[i][0] || bv[i][2] != av[i][1] || - av[i][1] != av[i][2] || bv[i][0] != av[i][3]) + bv[i][1] != av[i][2] || bv[i][0] != av[i][3]) break; - DRM_DEV_DEBUG_DRIVER(dev, "V' all match!! %d, %d", retry, i); + if (i == 5) { + DRM_DEV_DEBUG_DRIVER(dev, "V' all match!! %d", retry); return true; } } -- cgit v1.2.3-59-g8ed1b From badff5fed9ce968b22ae2d4c4239e2f3223987b2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 22 Jan 2025 17:17:55 +0200 Subject: drm/i915/fbdev: Use fb->normal_view.gtt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grab the GTT view for the fbdev fb pinning from fb->normal_view.gtt instead of having and extra one on the stack. Seems safer in case we ever put any new information into normal GTT views. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250122151755.6928-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fbdev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 833cded53d37..301b5fd301a2 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -177,9 +177,6 @@ static int intelfb_create(struct drm_fb_helper *helper, struct intel_framebuffer *fb = ifbdev->fb; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = to_i915(dev); - const struct i915_gtt_view view = { - .type = I915_GTT_VIEW_NORMAL, - }; intel_wakeref_t wakeref; struct fb_info *info; struct i915_vma *vma; @@ -226,7 +223,7 @@ static int intelfb_create(struct drm_fb_helper *helper, * This also validates that any existing fb inherited from the * BIOS is suitable for own access. */ - vma = intel_fb_pin_to_ggtt(&fb->base, &view, + vma = intel_fb_pin_to_ggtt(&fb->base, &fb->normal_view.gtt, fb->min_alignment, 0, intel_fb_view_vtd_guard(&fb->base, &fb->normal_view, DRM_MODE_ROTATE_0), -- cgit v1.2.3-59-g8ed1b From 93ecd4fbad16c90a9aded8e599a4ef75dada9f82 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 6 Feb 2025 02:17:26 +0200 Subject: drm/i915/dp_mst: Fix getting display pointer in intel_dp_mst_compute_min_hblank() The MST intel_connector::encoder pointer is NULL if the connector hasn't been enabled before, so it can't be used to retrieve the display pointer. Use instead the crtc_state and drop the unused connector parameter. v2: Use the crtc_state and drop the unused connector parameter. Fixes: a5ebe00c2ace ("drm/i915/dp: Guarantee a minimum HBlank time") Reported-and-tested-by: Khaled Almahallawy Closes: https://lore.kernel.org/all/16754ee4cd21d99c1e81c5953134b496dd07630f.camel@intel.com Reviewed-by: Khaled Almahallawy #v1 Cc: Arun R Murthy Cc: Suraj Kandpal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250206001726.3021787-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index cc6e4ca37519..2324ca8f6096 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -210,11 +210,9 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec } static void intel_dp_mst_compute_min_hblank(struct intel_crtc_state *crtc_state, - struct intel_connector *connector, int bpp_x16) { - struct intel_encoder *encoder = connector->encoder; - struct intel_display *display = to_intel_display(encoder); + struct intel_display *display = to_intel_display(crtc_state); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int symbol_size = intel_dp_is_uhbr(crtc_state) ? 32 : 8; @@ -301,7 +299,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state, false, dsc_slice_count, link_bpp_x16); - intel_dp_mst_compute_min_hblank(crtc_state, connector, link_bpp_x16); + intel_dp_mst_compute_min_hblank(crtc_state, link_bpp_x16); intel_dp_mst_compute_m_n(crtc_state, local_bw_overhead, -- cgit v1.2.3-59-g8ed1b From 9535c6a4c61cc0da28b9c9986aad200f1e1019e4 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 6 Feb 2025 12:02:48 +0530 Subject: drm/i915/backlight: Use proper interface based on eDP version eDP is supposed to use VESA interface when using revision 1.5 and above, use Intel interface for backlight control otherwise. Add check to use correct interface. Signed-off-by: Suraj Kandpal Tested-by: Ben Kao Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20250206063253.2827017-4-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') 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 c846ef4acf5b..09e82f24d030 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -604,6 +604,7 @@ static const struct intel_panel_bl_funcs intel_dp_vesa_bl_funcs = { int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) { struct intel_display *display = to_intel_display(connector); + struct intel_dp *intel_dp = intel_attached_dp(connector); struct drm_device *dev = connector->base.dev; struct intel_panel *panel = &connector->panel; bool try_intel_interface = false, try_vesa_interface = false; @@ -640,6 +641,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) break; } + /* For eDP 1.5 and above we are supposed to use VESA interface for brightness control */ + if (intel_dp->edp_dpcd[0] >= DP_EDP_15) + try_vesa_interface = true; + /* * Since Intel has their own backlight control interface, the majority of machines out there * using DPCD backlight controls with Intel GPUs will be using this interface as opposed to @@ -653,7 +658,8 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) * backlight interface at all. This means that the only sensible way for us to detect both * interfaces is to probe for Intel's first, and VESA's second. */ - if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector)) { + if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector) && + intel_dp->edp_dpcd[0] <= DP_EDP_14b) { drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Using Intel proprietary eDP backlight controls\n", connector->base.base.id, connector->base.name); panel->backlight.funcs = &intel_dp_hdr_bl_funcs; -- cgit v1.2.3-59-g8ed1b From 64481497924d8055fa7d6e60948ca899fe341cb6 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 6 Feb 2025 12:02:49 +0530 Subject: drm/i915/backlight: Check Luminance based brightness control for VESA Check if we are capable of controlling brightness via luminance which is dependent on PANEL_LUMINANCE_CONTROL_CAPABLE bit being set on EDP_GENERAL_CAPABILITY_2 register. --v2 -Prefer using luminance rather than nits [Jani] -Fix commit message --v3 -Fix the bit name used in commit message [Arun] -Use correct edp_dpcd[] to check the capability [Arun] Signed-off-by: Suraj Kandpal Tested-by: Ben Kao Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20250206063253.2827017-5-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index d8a3d4d6aedf..6a82c6ade549 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -413,6 +413,7 @@ struct intel_panel { union { struct { struct drm_edp_backlight_info info; + bool luminance_control_support; } vesa; struct { bool sdr_uses_aux; 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 09e82f24d030..2599aa39b21d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -575,6 +575,15 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector) { struct intel_display *display = to_intel_display(connector); struct intel_dp *intel_dp = intel_attached_dp(connector); + struct intel_panel *panel = &connector->panel; + + if ((intel_dp->edp_dpcd[3] & DP_EDP_PANEL_LUMINANCE_CONTROL_CAPABLE)) { + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] AUX Luminance Based Backlight Control Supported!\n", + connector->base.base.id, connector->base.name); + panel->backlight.edp.vesa.luminance_control_support = true; + return true; + } if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) { drm_dbg_kms(display->drm, -- cgit v1.2.3-59-g8ed1b From 3f8a009a794eac8f5b7fac0242d321cc4581303d Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 6 Feb 2025 12:02:50 +0530 Subject: drm/i915/backlight: Modify function to get VESA brightness in Nits Modify vesa_get_brightness function to take into account luminance_control_support and based on that read the appropriate register and return the value. --v2 -Changes since we now use luminance instead of nits Signed-off-by: Suraj Kandpal Tested-by: Ben Kao Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20250206063253.2827017-6-suraj.kandpal@intel.com --- .../gpu/drm/i915/display/intel_dp_aux_backlight.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') 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 2599aa39b21d..ca5fc40fa13a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -451,6 +451,26 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi /* VESA backlight callbacks */ static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, enum pipe unused) { + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct intel_panel *panel = &connector->panel; + u8 buf[3]; + u32 val = 0; + int ret; + + if (panel->backlight.edp.vesa.luminance_control_support) { + ret = drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE, buf, + sizeof(buf)); + if (ret < 0) { + drm_err(intel_dp->aux.drm_dev, + "[CONNECTOR:%d:%s] Failed to read Luminance from DPCD\n", + connector->base.base.id, connector->base.name); + return 0; + } + + val |= buf[0] | buf[1] << 8 | buf[2] << 16; + return val / 1000; + } + return connector->panel.backlight.level; } -- cgit v1.2.3-59-g8ed1b From b68074efcfcf7d8226ddb0b1326298671a04a3f7 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 6 Feb 2025 12:02:51 +0530 Subject: drm/i915/backlight: Add function to change brightness in nits for VESA Create a function that fills in the value for PANEL_TARGET_LUMINANCE_VALUE which helps in changing the luminance in nits using VESA interface. --v2 -Prefer using luminance over nits [Jani] Signed-off-by: Suraj Kandpal Tested-by: Ben Kao Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20250206063253.2827017-7-suraj.kandpal@intel.com --- .../gpu/drm/i915/display/intel_dp_aux_backlight.c | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') 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 ca5fc40fa13a..b0640b5128b1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -474,6 +474,31 @@ static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, en return connector->panel.backlight.level; } +static int +intel_dp_aux_vesa_set_luminance(struct intel_connector *connector, u32 level) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + u8 buf[3]; + int ret; + + level = level * 1000; + level &= 0xffffff; + buf[0] = (level & 0x0000ff); + buf[1] = (level & 0x00ff00) >> 8; + buf[2] = (level & 0xff0000) >> 16; + + ret = drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE, + buf, sizeof(buf)); + if (ret != sizeof(buf)) { + drm_err(intel_dp->aux.drm_dev, + "%s: Failed to set VESA Aux Luminance: %d\n", + intel_dp->aux.name, ret); + return -EINVAL; + } else { + return 0; + } +} + static void intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u32 level) { @@ -481,6 +506,11 @@ intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u3 struct intel_panel *panel = &connector->panel; struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + if (panel->backlight.edp.vesa.luminance_control_support) { + if (!intel_dp_aux_vesa_set_luminance(connector, level)) + return; + } + if (!panel->backlight.edp.vesa.info.aux_set) { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); -- cgit v1.2.3-59-g8ed1b From 8d502933ac20afe97ec36fa8f0fd39bfee631b60 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 6 Feb 2025 12:02:52 +0530 Subject: drm/i915/backlight: Setup nits based luminance via VESA Modify backlight setup function for VESA interface to take into account the nits based luminance. --v2 -Prefer using luminance over nits [Jani] Signed-off-by: Suraj Kandpal Tested-by: Ben Kao Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20250206063253.2827017-8-suraj.kandpal@intel.com --- .../gpu/drm/i915/display/intel_dp_aux_backlight.c | 99 +++++++++++++--------- 1 file changed, 59 insertions(+), 40 deletions(-) (limited to 'drivers') 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 b0640b5128b1..301a4dfdfbe5 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -560,56 +560,75 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe) { struct intel_display *display = to_intel_display(connector); + struct drm_luminance_range_info *luminance_range = + &connector->base.display_info.luminance_range; struct intel_dp *intel_dp = intel_attached_dp(connector); struct intel_panel *panel = &connector->panel; u16 current_level; u8 current_mode; int ret; - ret = drm_edp_backlight_init(&intel_dp->aux, &panel->backlight.edp.vesa.info, - panel->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd, - ¤t_level, ¤t_mode); - if (ret < 0) - return ret; - - drm_dbg_kms(display->drm, - "[CONNECTOR:%d:%s] AUX VESA backlight enable is controlled through %s\n", - connector->base.base.id, connector->base.name, - dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_enable)); - drm_dbg_kms(display->drm, - "[CONNECTOR:%d:%s] AUX VESA backlight level is controlled through %s\n", - connector->base.base.id, connector->base.name, - dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_set)); - - if (!panel->backlight.edp.vesa.info.aux_set || !panel->backlight.edp.vesa.info.aux_enable) { - ret = panel->backlight.pwm_funcs->setup(connector, pipe); - if (ret < 0) { - drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to setup PWM backlight controls for eDP backlight: %d\n", - connector->base.base.id, connector->base.name, ret); - return ret; - } - } - - if (panel->backlight.edp.vesa.info.aux_set) { - panel->backlight.max = panel->backlight.edp.vesa.info.max; - panel->backlight.min = 0; - if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { - panel->backlight.level = current_level; - panel->backlight.enabled = panel->backlight.level != 0; + if (panel->backlight.edp.vesa.luminance_control_support) { + if (luminance_range->max_luminance) { + panel->backlight.max = luminance_range->max_luminance; + panel->backlight.min = luminance_range->min_luminance; } else { - panel->backlight.level = panel->backlight.max; - panel->backlight.enabled = false; + panel->backlight.max = 512; + panel->backlight.min = 0; } + panel->backlight.level = intel_dp_aux_vesa_get_backlight(connector, 0); + panel->backlight.enabled = panel->backlight.level != 0; + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] AUX VESA Nits backlight level is controlled through DPCD\n", + connector->base.base.id, connector->base.name); } else { - panel->backlight.max = panel->backlight.pwm_level_max; - panel->backlight.min = panel->backlight.pwm_level_min; - if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_PWM) { - panel->backlight.level = panel->backlight.pwm_funcs->get(connector, pipe); - panel->backlight.enabled = panel->backlight.pwm_enabled; + ret = drm_edp_backlight_init(&intel_dp->aux, &panel->backlight.edp.vesa.info, + panel->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd, + ¤t_level, ¤t_mode); + if (ret < 0) + return ret; + + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] AUX VESA backlight enable is controlled through %s\n", + connector->base.base.id, connector->base.name, + dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_enable)); + drm_dbg_kms(display->drm, + "[CONNECTOR:%d:%s] AUX VESA backlight level is controlled through %s\n", + connector->base.base.id, connector->base.name, + dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_set)); + + if (!panel->backlight.edp.vesa.info.aux_set || + !panel->backlight.edp.vesa.info.aux_enable) { + ret = panel->backlight.pwm_funcs->setup(connector, pipe); + if (ret < 0) { + drm_err(display->drm, + "[CONNECTOR:%d:%s] Failed to setup PWM backlight controls for eDP backlight: %d\n", + connector->base.base.id, connector->base.name, ret); + return ret; + } + } + + if (panel->backlight.edp.vesa.info.aux_set) { + panel->backlight.max = panel->backlight.edp.vesa.info.max; + panel->backlight.min = 0; + if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { + panel->backlight.level = current_level; + panel->backlight.enabled = panel->backlight.level != 0; + } else { + panel->backlight.level = panel->backlight.max; + panel->backlight.enabled = false; + } } else { - panel->backlight.level = panel->backlight.max; - panel->backlight.enabled = false; + panel->backlight.max = panel->backlight.pwm_level_max; + panel->backlight.min = panel->backlight.pwm_level_min; + if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_PWM) { + panel->backlight.level = + panel->backlight.pwm_funcs->get(connector, pipe); + panel->backlight.enabled = panel->backlight.pwm_enabled; + } else { + panel->backlight.level = panel->backlight.max; + panel->backlight.enabled = false; + } } } -- cgit v1.2.3-59-g8ed1b From a5efc8dcfe710fd63a0557d3512e8ff753c2e283 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 6 Feb 2025 12:02:53 +0530 Subject: drm/i915/backlight: Enable nits based luminance Enable nits based luminance by writing the PANEL_LUMINANCE_CONTROL bit and set the correct register to change brightness. Signed-off-by: Suraj Kandpal Tested-by: Ben Kao Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20250206063253.2827017-9-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') 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 301a4dfdfbe5..f53c8355d5be 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -527,6 +527,18 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state, struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = &connector->panel; struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + int ret; + + if (panel->backlight.edp.vesa.luminance_control_support) { + ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, + DP_EDP_PANEL_LUMINANCE_CONTROL_ENABLE); + + if (ret == 1) + return; + + if (!intel_dp_aux_vesa_set_luminance(connector, level)) + return; + } if (!panel->backlight.edp.vesa.info.aux_enable) { u32 pwm_level; @@ -550,6 +562,9 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state struct intel_panel *panel = &connector->panel; struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + if (panel->backlight.edp.vesa.luminance_control_support) + return; + drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info); if (!panel->backlight.edp.vesa.info.aux_enable) -- cgit v1.2.3-59-g8ed1b From 8a734b9359cfa1bdb805f5ca23e20bd99dd18a0a Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 9 Jan 2025 14:52:19 -0500 Subject: drm/xe: Fix PVC RPe and RPa information A simple lazy buggy copy and paste of the PVC comment has brought the attention to the incorrect masks of the PVC register for RPa and RPe. So, let's fix them all. Cc: Lucas De Marchi Cc: Vinay Belgaumkar Reviewed-by: Vinay Belgaumkar Link: https://patchwork.freedesktop.org/patch/msgid/20250109195219.658557-1-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc_pc.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index 43f9617baba2..02409eedb914 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -363,16 +363,17 @@ static void tgl_update_rpa_value(struct xe_guc_pc *pc) u32 reg; /* - * For PVC we still need to use fused RP1 as the approximation for RPe - * For other platforms than PVC we get the resolved RPe directly from + * For PVC we still need to use fused RP0 as the approximation for RPa + * For other platforms than PVC we get the resolved RPa directly from * PCODE at a different register */ - if (xe->info.platform == XE_PVC) + if (xe->info.platform == XE_PVC) { reg = xe_mmio_read32(>->mmio, PVC_RP_STATE_CAP); - else + pc->rpa_freq = REG_FIELD_GET(RP0_MASK, reg) * GT_FREQUENCY_MULTIPLIER; + } else { reg = xe_mmio_read32(>->mmio, FREQ_INFO_REC); - - pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER; + pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER; + } } static void tgl_update_rpe_value(struct xe_guc_pc *pc) @@ -386,12 +387,13 @@ static void tgl_update_rpe_value(struct xe_guc_pc *pc) * For other platforms than PVC we get the resolved RPe directly from * PCODE at a different register */ - if (xe->info.platform == XE_PVC) + if (xe->info.platform == XE_PVC) { reg = xe_mmio_read32(>->mmio, PVC_RP_STATE_CAP); - else + pc->rpe_freq = REG_FIELD_GET(RP1_MASK, reg) * GT_FREQUENCY_MULTIPLIER; + } else { reg = xe_mmio_read32(>->mmio, FREQ_INFO_REC); - - pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER; + pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER; + } } static void pc_update_rp_values(struct xe_guc_pc *pc) -- cgit v1.2.3-59-g8ed1b From 01aebfaeff324d21f559a696016e13640f59b297 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 5 Feb 2025 13:01:50 +0100 Subject: drm/xe: Don't treat SR-IOV platforms as reclaim unsafe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit a4d1c5d0b99b ("drm/xe/pf: Move VFs reprovisioning to worker") and commit 78d5d1e20d1d ("drm/xe/relay: Don't use GFP_KERNEL for new transactions") we should have no more lockdep dependencies on the reclaim path when running in the SRIOV mode so we believe that we can now mark SRIOV driver as reclaim safe. Signed-off-by: Michal Wajdeczko Cc: Thomas Hellström Cc: Jonathan Cavitt Cc: Matthew Brost Tested-by: Marcin Bernatowicz Reviewed-by: Marcin Bernatowicz Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20250205120150.896-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index 35dd1757b40b..12200be7b43d 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -91,7 +91,7 @@ static struct lockdep_map xe_pm_runtime_nod3cold_map = { */ bool xe_rpm_reclaim_safe(const struct xe_device *xe) { - return !xe->d3cold.capable && !xe->info.has_sriov; + return !xe->d3cold.capable; } static void xe_rpm_lockmap_acquire(const struct xe_device *xe) -- cgit v1.2.3-59-g8ed1b From faa5259b1ea0f6237c1b8ff24aa3ce4b6faa2890 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 6 Feb 2025 10:20:00 +0530 Subject: drm/i915/display: Skip state checker for AS SDP infoframe enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid full modeset by skipping infoframe.enable check when toggling AS SDP while enabling VRR, preventing full modeset while pipe config changes. --v2: - Add check for exclude_infoframe. (Ankit) - Update commit message. (Ankit) --v3: - Optimise PIPE_CONF_CHECK for infoframes.enable. [Ankit] Signed-off-by: Mitul Golani Reviewed-by: Jouni Högander Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250206045001.2919360-2-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 60867b5b03ec..b68ccf12c439 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5388,6 +5388,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct drm_printer p; + u32 exclude_infoframes = 0; bool ret = true; if (fastset) @@ -5743,11 +5744,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(min_voltage_level); if (current_config->has_psr || pipe_config->has_psr) - PIPE_CONF_CHECK_X_WITH_MASK(infoframes.enable, - ~intel_hdmi_infoframe_enable(DP_SDP_VSC)); - else - PIPE_CONF_CHECK_X(infoframes.enable); + exclude_infoframes |= intel_hdmi_infoframe_enable(DP_SDP_VSC); + + if (current_config->vrr.enable || pipe_config->vrr.enable) + exclude_infoframes |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); + PIPE_CONF_CHECK_X_WITH_MASK(infoframes.enable, ~exclude_infoframes); PIPE_CONF_CHECK_X(infoframes.gcp); PIPE_CONF_CHECK_INFOFRAME(avi); PIPE_CONF_CHECK_INFOFRAME(spd); -- cgit v1.2.3-59-g8ed1b From 19214cd74716891be6fcc0fd90c634b3963d5ed2 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 6 Feb 2025 10:20:01 +0530 Subject: Revert "drm/i915/dp: Compute as_sdp based on if vrr possible" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 08277aa5d5a44befd71717de35b956f55e1e8401. Compute AS SDP params only when VRR is enabled to maintain PSR exclusivity. Signed-off-by: Mitul Golani Reviewed-by: Jouni Högander Signed-off-by: Ankit Nautiyal Link: https://patchwork.freedesktop.org/patch/msgid/20250206045001.2919360-3-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 7127cda64828..7463478eef92 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2817,7 +2817,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - if (!intel_vrr_possible(crtc_state) || !intel_dp->as_sdp_supported) + if (!crtc_state->vrr.enable || !intel_dp->as_sdp_supported) return; crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); -- cgit v1.2.3-59-g8ed1b From 5b380838930f1fb74d38f34ca4bff43416db01c3 Mon Sep 17 00:00:00 2001 From: Francois Dugast Date: Thu, 6 Feb 2025 14:45:50 +0100 Subject: drm/xe: Add stats for vma page faults Add new entries in stats for vma page faults. If CONFIG_DEBUG_FS is enabled, the count and number of bytes can be viewed per GT in the stat debugfs file. This helps when testing, to confirm page faults have been triggered as expected. It also helps when looking at the performance impact of page faults. Data is simply collected when entering the page fault handler so there is no indication whether it completed successfully, with or without retries, etc. Example output: cat /sys/kernel/debug/dri/0/gt0/stats tlb_inval_count: 129 vma_pagefault_count: 12 vma_pagefault_bytes: 98304 v2: Rebase Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20250206134551.1321265-1-francois.dugast@intel.com Signed-off-by: Francois Dugast --- drivers/gpu/drm/xe/xe_gt_pagefault.c | 10 +++++++--- drivers/gpu/drm/xe/xe_gt_stats.c | 2 ++ drivers/gpu/drm/xe/xe_gt_stats_types.h | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index cb92fb5cbc75..46701ca11ce0 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -14,6 +14,7 @@ #include "abi/guc_actions_abi.h" #include "xe_bo.h" #include "xe_gt.h" +#include "xe_gt_stats.h" #include "xe_gt_tlb_invalidation.h" #include "xe_guc.h" #include "xe_guc_ct.h" @@ -124,16 +125,20 @@ static int xe_pf_begin(struct drm_exec *exec, struct xe_vma *vma, return 0; } -static int handle_vma_pagefault(struct xe_tile *tile, struct pagefault *pf, +static int handle_vma_pagefault(struct xe_gt *gt, struct pagefault *pf, struct xe_vma *vma) { struct xe_vm *vm = xe_vma_vm(vma); + struct xe_tile *tile = gt_to_tile(gt); struct drm_exec exec; struct dma_fence *fence; ktime_t end = 0; int err; bool atomic; + xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT, 1); + xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_BYTES, xe_vma_size(vma)); + trace_xe_vma_pagefault(vma); atomic = access_is_atomic(pf->access_type); @@ -202,7 +207,6 @@ static struct xe_vm *asid_to_vm(struct xe_device *xe, u32 asid) static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) { struct xe_device *xe = gt_to_xe(gt); - struct xe_tile *tile = gt_to_tile(gt); struct xe_vm *vm; struct xe_vma *vma = NULL; int err; @@ -231,7 +235,7 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) goto unlock_vm; } - err = handle_vma_pagefault(tile, pf, vma); + err = handle_vma_pagefault(gt, pf, vma); unlock_vm: if (!err) diff --git a/drivers/gpu/drm/xe/xe_gt_stats.c b/drivers/gpu/drm/xe/xe_gt_stats.c index 7a6c1d808e41..2e9879ea4674 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats.c +++ b/drivers/gpu/drm/xe/xe_gt_stats.c @@ -28,6 +28,8 @@ void xe_gt_stats_incr(struct xe_gt *gt, const enum xe_gt_stats_id id, int incr) static const char *const stat_description[__XE_GT_STATS_NUM_IDS] = { "tlb_inval_count", + "vma_pagefault_count", + "vma_pagefault_bytes", }; /** diff --git a/drivers/gpu/drm/xe/xe_gt_stats_types.h b/drivers/gpu/drm/xe/xe_gt_stats_types.h index 2fc055e39f27..b072bd80c4b9 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats_types.h +++ b/drivers/gpu/drm/xe/xe_gt_stats_types.h @@ -8,6 +8,8 @@ enum xe_gt_stats_id { XE_GT_STATS_ID_TLB_INVAL, + XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT, + XE_GT_STATS_ID_VMA_PAGEFAULT_BYTES, /* must be the last entry */ __XE_GT_STATS_NUM_IDS, }; -- cgit v1.2.3-59-g8ed1b From 9e35a4edb837627849063d61d46968bfc691c484 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 6 Feb 2025 18:46:24 +0200 Subject: drm/i915/dp_mst: Fix disabling the minimum HBlank time Disable the minimum HBlank time only on LNL+, where this functionality and corresponding register exists. Bspec: 74379 Fixes: a5ebe00c2ace ("drm/i915/dp: Guarantee a minimum HBlank time") Cc: Arun R Murthy Cc: Suraj Kandpal Reviewed-by: Suraj Kandpal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250206164624.3185280-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 2324ca8f6096..411b7322d460 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1006,7 +1006,8 @@ static void mst_stream_disable(struct intel_atomic_state *state, intel_dp_sink_disable_decompression(state, connector, old_crtc_state); - intel_de_write(display, DP_MIN_HBLANK_CTL(trans), 0x00); + if (DISPLAY_VER(display) >= 20) + intel_de_write(display, DP_MIN_HBLANK_CTL(trans), 0); } static void mst_stream_post_disable(struct intel_atomic_state *state, -- cgit v1.2.3-59-g8ed1b From af6c2b7c46e16701fba44a21326cb634786e3e71 Mon Sep 17 00:00:00 2001 From: Adrián Larumbe Date: Thu, 30 Jan 2025 17:28:10 +0000 Subject: drm/file: Add fdinfo helper for printing regions with prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is motivated by the desire of some drivers (eg. Panthor) to print the size of internal memory regions with a prefix that reflects the driver name, as suggested in the previous documentation commit. That means adding a new argument to print_size and making it available for DRM users. Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Signed-off-by: Adrián Larumbe Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20250130172851.941597-3-adrian.larumbe@collabora.com --- drivers/gpu/drm/drm_file.c | 26 ++++++++++++++++++-------- include/drm/drm_file.h | 5 +++++ 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 2289e71e2fa2..c299cd94d3f7 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -830,8 +830,11 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e) } EXPORT_SYMBOL(drm_send_event); -static void print_size(struct drm_printer *p, const char *stat, - const char *region, u64 sz) +void drm_fdinfo_print_size(struct drm_printer *p, + const char *prefix, + const char *stat, + const char *region, + u64 sz) { const char *units[] = {"", " KiB", " MiB"}; unsigned u; @@ -842,8 +845,10 @@ static void print_size(struct drm_printer *p, const char *stat, sz = div_u64(sz, SZ_1K); } - drm_printf(p, "drm-%s-%s:\t%llu%s\n", stat, region, sz, units[u]); + drm_printf(p, "%s-%s-%s:\t%llu%s\n", + prefix, stat, region, sz, units[u]); } +EXPORT_SYMBOL(drm_fdinfo_print_size); int drm_memory_stats_is_zero(const struct drm_memory_stats *stats) { @@ -868,17 +873,22 @@ void drm_print_memory_stats(struct drm_printer *p, enum drm_gem_object_status supported_status, const char *region) { - print_size(p, "total", region, stats->private + stats->shared); - print_size(p, "shared", region, stats->shared); + const char *prefix = "drm"; + + drm_fdinfo_print_size(p, prefix, "total", region, + stats->private + stats->shared); + drm_fdinfo_print_size(p, prefix, "shared", region, stats->shared); if (supported_status & DRM_GEM_OBJECT_ACTIVE) - print_size(p, "active", region, stats->active); + drm_fdinfo_print_size(p, prefix, "active", region, stats->active); if (supported_status & DRM_GEM_OBJECT_RESIDENT) - print_size(p, "resident", region, stats->resident); + drm_fdinfo_print_size(p, prefix, "resident", region, + stats->resident); if (supported_status & DRM_GEM_OBJECT_PURGEABLE) - print_size(p, "purgeable", region, stats->purgeable); + drm_fdinfo_print_size(p, prefix, "purgeable", region, + stats->purgeable); } EXPORT_SYMBOL(drm_print_memory_stats); diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index ef817926cddd..94d365b22505 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -495,6 +495,11 @@ struct drm_memory_stats { enum drm_gem_object_status; int drm_memory_stats_is_zero(const struct drm_memory_stats *stats); +void drm_fdinfo_print_size(struct drm_printer *p, + const char *prefix, + const char *stat, + const char *region, + u64 sz); void drm_print_memory_stats(struct drm_printer *p, const struct drm_memory_stats *stats, enum drm_gem_object_status supported_status, -- cgit v1.2.3-59-g8ed1b From 434e5ca5b5d7ea415670d4fcb399d90d355a1e38 Mon Sep 17 00:00:00 2001 From: Adrián Larumbe Date: Thu, 30 Jan 2025 17:28:11 +0000 Subject: drm/panthor: Expose size of driver internal BO's over fdinfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will display the sizes of kenrel BO's bound to an open file, which are otherwise not exposed to UM through a handle. The sizes recorded are as follows: - Per group: suspend buffer, protm-suspend buffer, syncobjcs - Per queue: ringbuffer, profiling slots, firmware interface - For all heaps in all heap pools across all VM's bound to an open file, record size of all heap chuks, and for each pool the gpu_context BO too. This does not record the size of FW regions, as these aren't bound to a specific open file and remain active through the whole life of the driver. Reviewed-by: Liviu Dudau Reviewed-by: Mihail Atanassov Reviewed-by: Steven Price Reviewed-by: Boris Brezillon Signed-off-by: Adrián Larumbe Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20250130172851.941597-4-adrian.larumbe@collabora.com --- drivers/gpu/drm/panthor/panthor_drv.c | 14 +++++++++ drivers/gpu/drm/panthor/panthor_heap.c | 26 +++++++++++++++ drivers/gpu/drm/panthor/panthor_heap.h | 2 ++ drivers/gpu/drm/panthor/panthor_mmu.c | 33 +++++++++++++++++++ drivers/gpu/drm/panthor/panthor_mmu.h | 3 ++ drivers/gpu/drm/panthor/panthor_sched.c | 56 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/panthor/panthor_sched.h | 3 ++ 7 files changed, 136 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c index d5dcd3d1b33a..310bb44abe1a 100644 --- a/drivers/gpu/drm/panthor/panthor_drv.c +++ b/drivers/gpu/drm/panthor/panthor_drv.c @@ -1457,12 +1457,26 @@ static void panthor_gpu_show_fdinfo(struct panthor_device *ptdev, drm_printf(p, "drm-curfreq-panthor:\t%lu Hz\n", ptdev->current_frequency); } +static void panthor_show_internal_memory_stats(struct drm_printer *p, struct drm_file *file) +{ + char *drv_name = file->minor->dev->driver->name; + struct panthor_file *pfile = file->driver_priv; + struct drm_memory_stats stats = {0}; + + panthor_fdinfo_gather_group_mem_info(pfile, &stats); + panthor_vm_heaps_sizes(pfile, &stats); + + drm_fdinfo_print_size(p, drv_name, "resident", "memory", stats.resident); + drm_fdinfo_print_size(p, drv_name, "active", "memory", stats.active); +} + static void panthor_show_fdinfo(struct drm_printer *p, struct drm_file *file) { struct drm_device *dev = file->minor->dev; struct panthor_device *ptdev = container_of(dev, struct panthor_device, base); panthor_gpu_show_fdinfo(ptdev, file->driver_priv, p); + panthor_show_internal_memory_stats(p, file); drm_show_memory_stats(p, file); } diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c index 3796a9eb22af..db0285ce5812 100644 --- a/drivers/gpu/drm/panthor/panthor_heap.c +++ b/drivers/gpu/drm/panthor/panthor_heap.c @@ -603,3 +603,29 @@ void panthor_heap_pool_destroy(struct panthor_heap_pool *pool) panthor_heap_pool_put(pool); } + +/** + * panthor_heap_pool_size() - Calculate size of all chunks across all heaps in a pool + * @pool: Pool whose total chunk size to calculate. + * + * This function adds the size of all heap chunks across all heaps in the + * argument pool. It also adds the size of the gpu contexts kernel bo. + * It is meant to be used by fdinfo for displaying the size of internal + * driver BO's that aren't exposed to userspace through a GEM handle. + * + */ +size_t panthor_heap_pool_size(struct panthor_heap_pool *pool) +{ + struct panthor_heap *heap; + unsigned long i; + size_t size = 0; + + down_read(&pool->lock); + xa_for_each(&pool->xa, i, heap) + size += heap->chunk_size * heap->chunk_count; + up_read(&pool->lock); + + size += pool->gpu_contexts->obj->size; + + return size; +} diff --git a/drivers/gpu/drm/panthor/panthor_heap.h b/drivers/gpu/drm/panthor/panthor_heap.h index 25a5f2bba445..e3358d4e8edb 100644 --- a/drivers/gpu/drm/panthor/panthor_heap.h +++ b/drivers/gpu/drm/panthor/panthor_heap.h @@ -27,6 +27,8 @@ struct panthor_heap_pool * panthor_heap_pool_get(struct panthor_heap_pool *pool); void panthor_heap_pool_put(struct panthor_heap_pool *pool); +size_t panthor_heap_pool_size(struct panthor_heap_pool *pool); + int panthor_heap_grow(struct panthor_heap_pool *pool, u64 heap_gpu_va, u32 renderpasses_in_flight, diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c index 5ce80e2532d5..0a4e352b5505 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -1944,6 +1944,39 @@ struct panthor_heap_pool *panthor_vm_get_heap_pool(struct panthor_vm *vm, bool c return pool; } +/** + * panthor_vm_heaps_sizes() - Calculate size of all heap chunks across all + * heaps over all the heap pools in a VM + * @pfile: File. + * @stats: Memory stats to be updated. + * + * Calculate all heap chunk sizes in all heap pools bound to a VM. If the VM + * is active, record the size as active as well. + */ +void panthor_vm_heaps_sizes(struct panthor_file *pfile, struct drm_memory_stats *stats) +{ + struct panthor_vm *vm; + unsigned long i; + + if (!pfile->vms) + return; + + xa_lock(&pfile->vms->xa); + xa_for_each(&pfile->vms->xa, i, vm) { + size_t size = 0; + + mutex_lock(&vm->heaps.lock); + if (vm->heaps.pool) + size = panthor_heap_pool_size(vm->heaps.pool); + mutex_unlock(&vm->heaps.lock); + + stats->resident += size; + if (vm->as.id >= 0) + stats->active += size; + } + xa_unlock(&pfile->vms->xa); +} + static u64 mair_to_memattr(u64 mair, bool coherent) { u64 memattr = 0; diff --git a/drivers/gpu/drm/panthor/panthor_mmu.h b/drivers/gpu/drm/panthor/panthor_mmu.h index 8d21e83d8aba..fc274637114e 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.h +++ b/drivers/gpu/drm/panthor/panthor_mmu.h @@ -9,6 +9,7 @@ struct drm_exec; struct drm_sched_job; +struct drm_memory_stats; struct panthor_gem_object; struct panthor_heap_pool; struct panthor_vm; @@ -37,6 +38,8 @@ int panthor_vm_flush_all(struct panthor_vm *vm); struct panthor_heap_pool * panthor_vm_get_heap_pool(struct panthor_vm *vm, bool create); +void panthor_vm_heaps_sizes(struct panthor_file *pfile, struct drm_memory_stats *stats); + struct panthor_vm *panthor_vm_get(struct panthor_vm *vm); void panthor_vm_put(struct panthor_vm *vm); struct panthor_vm *panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index 5844a7f639e0..da87e6e81938 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -625,7 +625,7 @@ struct panthor_group { */ struct panthor_kernel_bo *syncobjs; - /** @fdinfo: Per-file total cycle and timestamp values reference. */ + /** @fdinfo: Per-file info exposed through /proc//fdinfo */ struct { /** @data: Total sampled values for jobs in queues from this group. */ struct panthor_gpu_usage data; @@ -635,6 +635,9 @@ struct panthor_group { * and job post-completion processing function */ struct mutex lock; + + /** @fdinfo.kbo_sizes: Aggregate size of private kernel BO's held by the group. */ + size_t kbo_sizes; } fdinfo; /** @state: Group state. */ @@ -3378,6 +3381,29 @@ err_free_queue: return ERR_PTR(ret); } +static void add_group_kbo_sizes(struct panthor_device *ptdev, + struct panthor_group *group) +{ + struct panthor_queue *queue; + int i; + + if (drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(group))) + return; + if (drm_WARN_ON(&ptdev->base, ptdev != group->ptdev)) + return; + + group->fdinfo.kbo_sizes += group->suspend_buf->obj->size; + group->fdinfo.kbo_sizes += group->protm_suspend_buf->obj->size; + group->fdinfo.kbo_sizes += group->syncobjs->obj->size; + + for (i = 0; i < group->queue_count; i++) { + queue = group->queues[i]; + group->fdinfo.kbo_sizes += queue->ringbuf->obj->size; + group->fdinfo.kbo_sizes += queue->iface.mem->obj->size; + group->fdinfo.kbo_sizes += queue->profiling.slots->obj->size; + } +} + #define MAX_GROUPS_PER_POOL 128 int panthor_group_create(struct panthor_file *pfile, @@ -3502,6 +3528,7 @@ int panthor_group_create(struct panthor_file *pfile, } mutex_unlock(&sched->reset.lock); + add_group_kbo_sizes(group->ptdev, group); mutex_init(&group->fdinfo.lock); return gid; @@ -3621,6 +3648,33 @@ void panthor_group_pool_destroy(struct panthor_file *pfile) pfile->groups = NULL; } +/** + * panthor_fdinfo_gather_group_mem_info() - Retrieve aggregate size of all private kernel BO's + * belonging to all the groups owned by an open Panthor file + * @pfile: File. + * @stats: Memory statistics to be updated. + * + */ +void +panthor_fdinfo_gather_group_mem_info(struct panthor_file *pfile, + struct drm_memory_stats *stats) +{ + struct panthor_group_pool *gpool = pfile->groups; + struct panthor_group *group; + unsigned long i; + + if (IS_ERR_OR_NULL(gpool)) + return; + + xa_lock(&gpool->xa); + xa_for_each(&gpool->xa, i, group) { + stats->resident += group->fdinfo.kbo_sizes; + if (group->csg_id >= 0) + stats->active += group->fdinfo.kbo_sizes; + } + xa_unlock(&gpool->xa); +} + static void job_release(struct kref *ref) { struct panthor_job *job = container_of(ref, struct panthor_job, refcount); diff --git a/drivers/gpu/drm/panthor/panthor_sched.h b/drivers/gpu/drm/panthor/panthor_sched.h index 5ae6b4bde7c5..e650a445cf50 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.h +++ b/drivers/gpu/drm/panthor/panthor_sched.h @@ -9,6 +9,7 @@ struct dma_fence; struct drm_file; struct drm_gem_object; struct drm_sched_job; +struct drm_memory_stats; struct drm_panthor_group_create; struct drm_panthor_queue_create; struct drm_panthor_group_get_state; @@ -36,6 +37,8 @@ void panthor_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *job); int panthor_group_pool_create(struct panthor_file *pfile); void panthor_group_pool_destroy(struct panthor_file *pfile); +void panthor_fdinfo_gather_group_mem_info(struct panthor_file *pfile, + struct drm_memory_stats *stats); int panthor_sched_init(struct panthor_device *ptdev); void panthor_sched_unplug(struct panthor_device *ptdev); -- cgit v1.2.3-59-g8ed1b From 0590c94c3596d6c1a3d549ae611366f2ad4e1d8d Mon Sep 17 00:00:00 2001 From: Adrián Larumbe Date: Thu, 30 Jan 2025 17:28:13 +0000 Subject: drm/panthor: Fix race condition when gathering fdinfo group samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e16635d88fa0 ("drm/panthor: add DRM fdinfo support") failed to protect access to groups with an xarray lock, which could lead to use-after-free errors. Fixes: e16635d88fa0 ("drm/panthor: add DRM fdinfo support") Reviewed-by: Boris Brezillon Reviewed-by: Steven Price Signed-off-by: Adrián Larumbe Signed-off-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20250130172851.941597-6-adrian.larumbe@collabora.com Link: https://patchwork.freedesktop.org/patch/msgid/20250107173310.88329-1-florent.tomasin@arm.com --- drivers/gpu/drm/panthor/panthor_sched.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index da87e6e81938..0b93bf83a9b2 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -2878,6 +2878,7 @@ void panthor_fdinfo_gather_group_samples(struct panthor_file *pfile) if (IS_ERR_OR_NULL(gpool)) return; + xa_lock(&gpool->xa); xa_for_each(&gpool->xa, i, group) { mutex_lock(&group->fdinfo.lock); pfile->stats.cycles += group->fdinfo.data.cycles; @@ -2886,6 +2887,7 @@ void panthor_fdinfo_gather_group_samples(struct panthor_file *pfile) group->fdinfo.data.time = 0; mutex_unlock(&group->fdinfo.lock); } + xa_unlock(&gpool->xa); } static void group_sync_upd_work(struct work_struct *work) -- cgit v1.2.3-59-g8ed1b From dbed4a797e00d98a4eaa971f1585091fad076a74 Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Tue, 28 Jan 2025 17:52:10 +0100 Subject: drm/panic: Better binary encoding in QR code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current encoding, is done by converting 13bits of input into 4 decimal digits, that are then encoded efficiently using the numeric encoding of the QR code specification. The Fido v2.2 specification [1] uses a similar approach for its QR-initiated authentication. The only difference is that it converts 7 bytes (56bits) of input into 17 decimal digits. The benefit is that the algorithm doesn't require to split input bytes into 13bits chunk, and the ratio is a bit better. This improvement was proposed by Jó Ágila Bitsch in [2]. drm_panic is still young, and the QR code feature is not widely used, so it's still time to switch to a common algorithm, shared with a widely used standard. I also changed the name of the url parameter, from zl= to z=, so the website can keep backward compatibility if needed. [1] https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#hybrid-qr-initiated [2] https://github.com/kdj0c/panic_report/issues/2 Signed-off-by: Jocelyn Falempe Acked-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250128165254.893204-1-jfalempe@redhat.com --- drivers/gpu/drm/drm_panic.c | 2 +- drivers/gpu/drm/drm_panic_qr.rs | 108 +++++++++++++--------------------------- 2 files changed, 36 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c index f128d345b16d..ab42a2b1567d 100644 --- a/drivers/gpu/drm/drm_panic.c +++ b/drivers/gpu/drm/drm_panic.c @@ -499,7 +499,7 @@ static int drm_panic_get_qr_code_url(u8 **qr_image) char *kmsg; int max_qr_data_size, url_len; - url_len = snprintf(url, sizeof(url), CONFIG_DRM_PANIC_SCREEN_QR_CODE_URL "?a=%s&v=%s&zl=", + url_len = snprintf(url, sizeof(url), CONFIG_DRM_PANIC_SCREEN_QR_CODE_URL "?a=%s&v=%s&z=", utsname()->machine, utsname()->release); max_qr_data_size = drm_panic_qr_max_data_size(panic_qr_version, url_len); diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs index bcf248f69252..62cb8a162483 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -13,12 +13,13 @@ //! The binary data must be a valid URL parameter, so the easiest way is //! to use base64 encoding. But this wastes 25% of data space, so the //! whole stack trace won't fit in the QR code. So instead it encodes -//! every 13bits of input into 4 decimal digits, and then uses the +//! every 7 bytes of input into 17 decimal digits, and then uses the //! efficient numeric encoding, that encode 3 decimal digits into -//! 10bits. This makes 39bits of compressed data into 12 decimal digits, -//! into 40bits in the QR code, so wasting only 2.5%. And the numbers are +//! 10bits. This makes 168bits of compressed data into 51 decimal digits, +//! into 170bits in the QR code, so wasting only 1.17%. And the numbers are //! valid URL parameter, so the website can do the reverse, to get the -//! binary data. +//! binary data. This is the same algorithm used by Fido v2.2 QR-initiated +//! authentication specification. //! //! Inspired by these 3 projects, all under MIT license: //! @@ -26,7 +27,6 @@ //! * //! * -use core::cmp; use kernel::str::CStr; #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] @@ -296,35 +296,11 @@ const MODE_BINARY: u16 = 4; /// Padding bytes. const PADDING: [u8; 2] = [236, 17]; -/// Get the next 13 bits of data, starting at specified offset (in bits). -fn get_next_13b(data: &[u8], offset: usize) -> Option<(u16, usize)> { - if offset < data.len() * 8 { - let size = cmp::min(13, data.len() * 8 - offset); - let byte_off = offset / 8; - let bit_off = offset % 8; - // `b` is 20 at max (`bit_off` <= 7 and `size` <= 13). - let b = (bit_off + size) as u16; - - let first_byte = (data[byte_off] << bit_off >> bit_off) as u16; - - let number = match b { - 0..=8 => first_byte >> (8 - b), - 9..=16 => (first_byte << (b - 8)) + (data[byte_off + 1] >> (16 - b)) as u16, - _ => { - (first_byte << (b - 8)) - + ((data[byte_off + 1] as u16) << (b - 16)) - + (data[byte_off + 2] >> (24 - b)) as u16 - } - }; - Some((number, size)) - } else { - None - } -} - /// Number of bits to encode characters in numeric mode. const NUM_CHARS_BITS: [usize; 4] = [0, 4, 7, 10]; -const POW10: [u16; 4] = [1, 10, 100, 1000]; +/// Number of decimal digits required to encode n bytes of binary data. +/// eg: you need 15 decimal digits to fit 6 bytes of binary data. +const BYTES_TO_DIGITS: [usize; 8] = [0, 3, 5, 8, 10, 13, 15, 17]; enum Segment<'a> { Numeric(&'a [u8]), @@ -360,13 +336,9 @@ impl Segment<'_> { match self { Segment::Binary(data) => data.len(), Segment::Numeric(data) => { - let data_bits = data.len() * 8; - let last_chars = match data_bits % 13 { - 1 => 1, - k => (k + 1) / 3, - }; - // 4 decimal numbers per 13bits + remainder. - 4 * (data_bits / 13) + last_chars + let last_chars = BYTES_TO_DIGITS[data.len() % 7]; + // 17 decimal numbers per 7bytes + remainder. + 17 * (data.len() / 7) + last_chars } } } @@ -403,7 +375,7 @@ impl Segment<'_> { struct SegmentIterator<'a> { segment: &'a Segment<'a>, offset: usize, - carry: u16, + carry: u64, carry_len: usize, } @@ -422,40 +394,30 @@ impl Iterator for SegmentIterator<'_> { } } Segment::Numeric(data) => { - if self.carry_len == 3 { - let out = (self.carry, NUM_CHARS_BITS[self.carry_len]); - self.carry_len = 0; - self.carry = 0; - Some(out) - } else if let Some((bits, size)) = get_next_13b(data, self.offset) { - self.offset += size; - let new_chars = match size { - 1 => 1, - k => (k + 1) / 3, - }; - if self.carry_len + new_chars > 3 { - self.carry_len = new_chars + self.carry_len - 3; - let out = ( - self.carry * POW10[new_chars - self.carry_len] - + bits / POW10[self.carry_len], - NUM_CHARS_BITS[3], - ); - self.carry = bits % POW10[self.carry_len]; - Some(out) - } else { - let out = ( - self.carry * POW10[new_chars] + bits, - NUM_CHARS_BITS[self.carry_len + new_chars], - ); - self.carry_len = 0; - Some(out) + if self.carry_len < 3 && self.offset < data.len() { + // If there are less than 3 decimal digits in the carry, + // take the next 7 bytes of input, and add them to the carry. + let mut buf = [0u8; 8]; + let len = 7.min(data.len() - self.offset); + buf[..len].copy_from_slice(&data[self.offset..self.offset + len]); + let chunk = u64::from_le_bytes(buf); + let pow = u64::pow(10, BYTES_TO_DIGITS[len] as u32); + self.carry = chunk + self.carry * pow; + self.offset += len; + self.carry_len += BYTES_TO_DIGITS[len]; + } + match self.carry_len { + 0 => None, + len => { + // take the next 3 decimal digits of the carry + // and return 10bits of numeric data. + let out_len = 3.min(len); + self.carry_len -= out_len; + let pow = u64::pow(10, self.carry_len as u32); + let out = (self.carry / pow) as u16; + self.carry = self.carry % pow; + Some((out, NUM_CHARS_BITS[out_len])) } - } else if self.carry_len > 0 { - let out = (self.carry, NUM_CHARS_BITS[self.carry_len]); - self.carry_len = 0; - Some(out) - } else { - None } } } -- cgit v1.2.3-59-g8ed1b From 6bb05b3631bd81227298b291b651dc7ec6ee0145 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 6 Feb 2025 22:45:45 +0100 Subject: drm/xe: Enable SR-IOV for PTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should now have sufficient changes in the driver to run it on PTL platforms in the SR-IOV Physical Function (PF) mode, that would allow us to enable SR-IOV Virtual Functions (VFs), and successfully probe our driver in the VF mode on enabled VF devices. To unblock SR-IOV PF mode you need to load xe with modparam: xe.max_vfs=7 Then to enable VFs it is sufficient to use: $ echo 7 > /sys/bus/pci/devices/0000:00:02.0/sriov_numvfs Note that in default auto-provisioning all VFs are allocated with some amount of shared resources (like unlimited GPU execution and preemption times, fair GGTT space, fair GuC context IDs range, ...) However with CONFIG_DEBUG_FS enabled it is possible to tweak most of the SR-IOV configuration parameters using attributes like: /sys/kernel/debug/dri/0000:00:02.0/gt0/ ├── pf │   ├── contexts_spare │   ├── doorbells_spare │   ├── exec_quantum_ms │   ├── ggtt_spare │   ├── preempt_timeout_us │   ├── sched_priority │   └── ... ├── vf1 │   ├── contexts_quota │   ├── doorbells_quota │   ├── exec_quantum_ms │   ├── ggtt_quota │   ├── preempt_timeout_us │   ├── sched_priority │   └── ... ├── vf2 │   └── ... : Signed-off-by: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Lucas De Marchi Cc: Thomas Hellstrom Acked-by: Rodrigo Vivi Reviewed-by: Jakub Kolakowski Tested-by: Marcin Bernatowicz Reviewed-by: Marcin Bernatowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250206214545.940-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index cfa1ad7a1f2d..663bfc29cddc 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -363,6 +363,7 @@ static const struct xe_device_desc ptl_desc = { PLATFORM(PANTHERLAKE), .dma_mask_size = 46, .has_display = true, + .has_sriov = true, .require_force_probe = true, }; -- cgit v1.2.3-59-g8ed1b From 05345cea4ff5a857612df3f10144dec685c07e6d Mon Sep 17 00:00:00 2001 From: Langyan Ye Date: Thu, 6 Feb 2025 21:13:00 +0800 Subject: drm/panel: panel-himax-hx83102: support for csot-pna957qt1-1 MIPI-DSI panel The csot-pna957qt1-1 is a 10.95" TFT panel. The MIPI controller on this panel is the same as the other panels here, so add this panel to this driver. Signed-off-by: Langyan Ye Reviewed-by: Neil Armstrong Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250206131300.1295111-4-yelangyan@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-himax-hx83102.c | 123 ++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c index 3644a7544b93..c3f4f5ee175d 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx83102.c +++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c @@ -43,6 +43,7 @@ #define HX83102_SETGIP1 0xd5 #define HX83102_SETGIP2 0xd6 #define HX83102_SETGIP3 0xd8 +#define HX83102_UNKNOWN_D9 0xd9 #define HX83102_SETGMA 0xe0 #define HX83102_UNKNOWN_E1 0xe1 #define HX83102_SETTP1 0xe7 @@ -291,6 +292,103 @@ static int boe_nv110wum_init(struct hx83102 *ctx) return dsi_ctx.accum_err; }; +static int csot_pna957qt1_1_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(60); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D9, 0xd2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb3, 0xb3, 0x31, 0xf1, 0x33, + 0xe0, 0x54, 0x36, 0x36, 0x3a, 0x3a, 0x32, 0x8b, 0x11, 0xe5, + 0x98); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x8b, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x2c, + 0x80, 0x3c, 0x9f, 0x22, 0x20, 0x00, 0x00, 0x98, 0x51); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x41, 0x41, 0x41, 0x41, 0x64, 0x64, + 0x40, 0x84, 0x64, 0x84, 0x01, 0x9d, 0x01, 0x02, 0x01, 0x00, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4, 0x80, 0x9c, 0x36, 0x00, + 0x0d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x32, 0x32, 0x22, 0x11, 0x22, 0xa0, + 0x31, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, + 0x36); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, 0x04, 0x2c, + 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x40, 0x04, + 0x08, 0x04, 0x08, 0x37, 0x07, 0x44, 0x37, 0x2b, 0x2b, 0x03, + 0x03, 0x32, 0x10, 0x22, 0x00, 0x25, 0x32, 0x10, 0x29, 0x00, + 0x29, 0x32, 0x10, 0x08, 0x00, 0x08, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, + 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x18, 0x18, 0x25, 0x24, 0x25, 0x24, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1e, 0x1e, 0x1e, 0x1e, 0x20, 0x20, 0x20, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x0a, 0x0e, 0x1a, 0x21, 0x28, 0x46, + 0x5c, 0x61, 0x63, 0x5e, 0x78, 0x7d, 0x80, 0x8e, 0x89, 0x90, + 0x98, 0xaa, 0xa8, 0x52, 0x59, 0x60, 0x6f, 0x06, 0x0a, 0x16, + 0x1d, 0x24, 0x46, 0x5c, 0x61, 0x6b, 0x66, 0x7c, 0x7d, 0x80, + 0x8e, 0x89, 0x90, 0x98, 0xaa, 0xa8, 0x52, 0x59, 0x60, 0x6f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xe0, 0x10, 0x10, 0x0d, 0x1e, 0x9d, + 0x02, 0x52, 0x9d, 0x14, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x64); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x05, 0x15, 0x55, 0x45, + 0x55, 0x50, 0x05, 0x15, 0x55, 0x45, 0x55, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x24, 0x01, 0x7e, 0x0f, + 0x7c, 0x10, 0xa0, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0, + 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, + 0x20, 0x9d, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x66, 0x81); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x0f, 0x2a, 0xaa, 0x8a, + 0xaa, 0xf0, 0x0f, 0x2a, 0xaa, 0x8a, 0xaa, 0xf0, 0x0a, 0x2a, + 0xaa, 0x8a, 0xaa, 0xa0, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + mipi_dsi_msleep(&dsi_ctx, 60); + + return dsi_ctx.accum_err; +}; + static int ivo_t109nw41_init(struct hx83102 *ctx) { struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; @@ -440,6 +538,28 @@ static const struct hx83102_panel_desc boe_nv110wum_desc = { .init = boe_nv110wum_init, }; +static const struct drm_display_mode csot_pna957qt1_1_default_mode = { + .clock = 177958, + .hdisplay = 1200, + .hsync_start = 1200 + 124, + .hsync_end = 1200 + 124 + 80, + .htotal = 1200 + 124 + 80 + 40, + .vdisplay = 1920, + .vsync_start = 1920 + 88, + .vsync_end = 1920 + 88 + 8, + .vtotal = 1920 + 88 + 8 + 38, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc csot_pna957qt1_1_desc = { + .modes = &csot_pna957qt1_1_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = csot_pna957qt1_1_init, +}; + static const struct drm_display_mode ivo_t109nw41_default_mode = { .clock = 167700, .hdisplay = 1200, @@ -683,6 +803,9 @@ static const struct of_device_id hx83102_of_match[] = { { .compatible = "boe,nv110wum-l60", .data = &boe_nv110wum_desc }, + { .compatible = "csot,pna957qt1-1", + .data = &csot_pna957qt1_1_desc + }, { .compatible = "ivo,t109nw41", .data = &ivo_t109nw41_desc }, -- cgit v1.2.3-59-g8ed1b From 6f3d9d0dd335290fa364048de5b3a440f1cf259f Mon Sep 17 00:00:00 2001 From: Ryosuke Yasuoka Date: Thu, 6 Feb 2025 19:42:59 +0900 Subject: drm/virtio: Add drm_panic support Virtio gpu supports the drm_panic module, which displays a message to the screen when a kernel panic occurs. It is supported where it has vmapped shmem BO. Signed-off-by: Jocelyn Falempe Signed-off-by: Ryosuke Yasuoka Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20250206104300.416014-1-ryasuoka@redhat.com --- drivers/gpu/drm/virtio/virtgpu_drv.h | 11 +++ drivers/gpu/drm/virtio/virtgpu_gem.c | 14 +++ drivers/gpu/drm/virtio/virtgpu_plane.c | 96 +++++++++++++++++++++ drivers/gpu/drm/virtio/virtgpu_vq.c | 151 +++++++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index f42ca9d8ed10..f17660a71a3e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -310,6 +310,7 @@ int virtio_gpu_mode_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args); +struct virtio_gpu_object_array *virtio_gpu_panic_array_alloc(void); struct virtio_gpu_object_array *virtio_gpu_array_alloc(u32 nents); struct virtio_gpu_object_array* virtio_gpu_array_from_handles(struct drm_file *drm_file, u32 *handles, u32 nents); @@ -334,12 +335,21 @@ void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev, struct virtio_gpu_fence *fence); void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo); +int virtio_gpu_panic_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, + uint64_t offset, + uint32_t width, uint32_t height, + uint32_t x, uint32_t y, + struct virtio_gpu_object_array *objs); void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, uint64_t offset, uint32_t width, uint32_t height, uint32_t x, uint32_t y, struct virtio_gpu_object_array *objs, struct virtio_gpu_fence *fence); +void virtio_gpu_panic_cmd_resource_flush(struct virtio_gpu_device *vgdev, + uint32_t resource_id, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height); void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev, uint32_t resource_id, uint32_t x, uint32_t y, @@ -408,6 +418,7 @@ void virtio_gpu_ctrl_ack(struct virtqueue *vq); void virtio_gpu_cursor_ack(struct virtqueue *vq); void virtio_gpu_dequeue_ctrl_func(struct work_struct *work); void virtio_gpu_dequeue_cursor_func(struct work_struct *work); +void virtio_gpu_panic_notify(struct virtio_gpu_device *vgdev); void virtio_gpu_notify(struct virtio_gpu_device *vgdev); int diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index 5aab588fc400..dde8fc1a3689 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -148,6 +148,20 @@ void virtio_gpu_gem_object_close(struct drm_gem_object *obj, virtio_gpu_notify(vgdev); } +/* For drm panic */ +struct virtio_gpu_object_array *virtio_gpu_panic_array_alloc(void) +{ + struct virtio_gpu_object_array *objs; + + objs = kmalloc(sizeof(struct virtio_gpu_object_array), GFP_ATOMIC); + if (!objs) + return NULL; + + objs->nents = 0; + objs->total = 1; + return objs; +} + struct virtio_gpu_object_array *virtio_gpu_array_alloc(u32 nents) { struct virtio_gpu_object_array *objs; diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 42aa554eca9f..a6f5a78f436a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "virtgpu_drv.h" @@ -127,6 +129,30 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, return ret; } +/* For drm panic */ +static int virtio_gpu_panic_update_dumb_bo(struct virtio_gpu_device *vgdev, + struct drm_plane_state *state, + struct drm_rect *rect) +{ + struct virtio_gpu_object *bo = + gem_to_virtio_gpu_obj(state->fb->obj[0]); + struct virtio_gpu_object_array *objs; + uint32_t w = rect->x2 - rect->x1; + uint32_t h = rect->y2 - rect->y1; + uint32_t x = rect->x1; + uint32_t y = rect->y1; + uint32_t off = x * state->fb->format->cpp[0] + + y * state->fb->pitches[0]; + + objs = virtio_gpu_panic_array_alloc(); + if (!objs) + return -ENOMEM; + virtio_gpu_array_add_obj(objs, &bo->base.base); + + return virtio_gpu_panic_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y, + objs); +} + static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev, struct drm_plane_state *state, struct drm_rect *rect) @@ -150,6 +176,24 @@ static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev, objs, NULL); } +/* For drm_panic */ +static void virtio_gpu_panic_resource_flush(struct drm_plane *plane, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height) +{ + struct drm_device *dev = plane->dev; + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_framebuffer *vgfb; + struct virtio_gpu_object *bo; + + vgfb = to_virtio_gpu_framebuffer(plane->state->fb); + bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); + + virtio_gpu_panic_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y, + width, height); + virtio_gpu_panic_notify(vgdev); +} + static void virtio_gpu_resource_flush(struct drm_plane *plane, uint32_t x, uint32_t y, uint32_t width, uint32_t height) @@ -446,11 +490,63 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane, virtio_gpu_cursor_ping(vgdev, output); } +static int virtio_drm_get_scanout_buffer(struct drm_plane *plane, + struct drm_scanout_buffer *sb) +{ + struct virtio_gpu_object *bo; + + if (!plane->state || !plane->state->fb || !plane->state->visible) + return -ENODEV; + + bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]); + + /* Only support mapped shmem bo */ + if (virtio_gpu_is_vram(bo) || bo->base.base.import_attach || !bo->base.vaddr) + return -ENODEV; + + iosys_map_set_vaddr(&sb->map[0], bo->base.vaddr); + + sb->format = plane->state->fb->format; + sb->height = plane->state->fb->height; + sb->width = plane->state->fb->width; + sb->pitch[0] = plane->state->fb->pitches[0]; + return 0; +} + +static void virtio_panic_flush(struct drm_plane *plane) +{ + struct virtio_gpu_object *bo; + struct drm_device *dev = plane->dev; + struct virtio_gpu_device *vgdev = dev->dev_private; + struct drm_rect rect; + + rect.x1 = 0; + rect.y1 = 0; + rect.x2 = plane->state->fb->width; + rect.y2 = plane->state->fb->height; + + bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]); + + if (bo->dumb) { + if (virtio_gpu_panic_update_dumb_bo(vgdev, plane->state, + &rect)) + return; + } + + virtio_gpu_panic_resource_flush(plane, + plane->state->src_x >> 16, + plane->state->src_y >> 16, + plane->state->src_w >> 16, + plane->state->src_h >> 16); +} + static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = { .prepare_fb = virtio_gpu_plane_prepare_fb, .cleanup_fb = virtio_gpu_plane_cleanup_fb, .atomic_check = virtio_gpu_plane_atomic_check, .atomic_update = virtio_gpu_primary_plane_update, + .get_scanout_buffer = virtio_drm_get_scanout_buffer, + .panic_flush = virtio_panic_flush, }; static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = { diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 062639250a4e..55a15e247dd1 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -86,6 +86,22 @@ void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev) vgdev->vbufs = NULL; } +/* For drm_panic */ +static struct virtio_gpu_vbuffer* +virtio_gpu_panic_get_vbuf(struct virtio_gpu_device *vgdev, int size) +{ + struct virtio_gpu_vbuffer *vbuf; + + vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_ATOMIC); + + vbuf->buf = (void *)vbuf + sizeof(*vbuf); + vbuf->size = size; + vbuf->resp_cb = NULL; + vbuf->resp_size = sizeof(struct virtio_gpu_ctrl_hdr); + vbuf->resp_buf = (void *)vbuf->buf + size; + return vbuf; +} + static struct virtio_gpu_vbuffer* virtio_gpu_get_vbuf(struct virtio_gpu_device *vgdev, int size, int resp_size, void *resp_buf, @@ -137,6 +153,18 @@ virtio_gpu_alloc_cursor(struct virtio_gpu_device *vgdev, return (struct virtio_gpu_update_cursor *)vbuf->buf; } +/* For drm_panic */ +static void *virtio_gpu_panic_alloc_cmd_resp(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer **vbuffer_p, + int cmd_size) +{ + struct virtio_gpu_vbuffer *vbuf; + + vbuf = virtio_gpu_panic_get_vbuf(vgdev, cmd_size); + *vbuffer_p = vbuf; + return (struct virtio_gpu_command *)vbuf->buf; +} + static void *virtio_gpu_alloc_cmd_resp(struct virtio_gpu_device *vgdev, virtio_gpu_resp_cb cb, struct virtio_gpu_vbuffer **vbuffer_p, @@ -311,6 +339,34 @@ static struct sg_table *vmalloc_to_sgt(char *data, uint32_t size, int *sg_ents) return sgt; } +/* For drm_panic */ +static int virtio_gpu_panic_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf, + int elemcnt, + struct scatterlist **sgs, + int outcnt, + int incnt) +{ + struct virtqueue *vq = vgdev->ctrlq.vq; + int ret; + + if (vgdev->has_indirect) + elemcnt = 1; + + if (vq->num_free < elemcnt) + return -ENOMEM; + + ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC); + WARN_ON(ret); + + vbuf->seqno = ++vgdev->ctrlq.seqno; + trace_virtio_gpu_cmd_queue(vq, virtio_gpu_vbuf_ctrl_hdr(vbuf), vbuf->seqno); + + atomic_inc(&vgdev->pending_commands); + + return 0; +} + static int virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, struct virtio_gpu_vbuffer *vbuf, struct virtio_gpu_fence *fence, @@ -368,6 +424,32 @@ again: return 0; } +/* For drm_panic */ +static int virtio_gpu_panic_queue_ctrl_buffer(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf) +{ + struct scatterlist *sgs[3], vcmd, vresp; + int elemcnt = 0, outcnt = 0, incnt = 0; + + /* set up vcmd */ + sg_init_one(&vcmd, vbuf->buf, vbuf->size); + elemcnt++; + sgs[outcnt] = &vcmd; + outcnt++; + + /* set up vresp */ + if (vbuf->resp_size) { + sg_init_one(&vresp, vbuf->resp_buf, vbuf->resp_size); + elemcnt++; + sgs[outcnt + incnt] = &vresp; + incnt++; + } + + return virtio_gpu_panic_queue_ctrl_sgs(vgdev, vbuf, + elemcnt, sgs, + outcnt, incnt); +} + static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, struct virtio_gpu_vbuffer *vbuf, struct virtio_gpu_fence *fence) @@ -422,6 +504,21 @@ static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, return ret; } +/* For drm_panic */ +void virtio_gpu_panic_notify(struct virtio_gpu_device *vgdev) +{ + bool notify; + + if (!atomic_read(&vgdev->pending_commands)) + return; + + atomic_set(&vgdev->pending_commands, 0); + notify = virtqueue_kick_prepare(vgdev->ctrlq.vq); + + if (notify) + virtqueue_notify(vgdev->ctrlq.vq); +} + void virtio_gpu_notify(struct virtio_gpu_device *vgdev) { bool notify; @@ -567,6 +664,29 @@ void virtio_gpu_cmd_set_scanout(struct virtio_gpu_device *vgdev, virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); } +/* For drm_panic */ +void virtio_gpu_panic_cmd_resource_flush(struct virtio_gpu_device *vgdev, + uint32_t resource_id, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height) +{ + struct virtio_gpu_resource_flush *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_panic_alloc_cmd_resp(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + vbuf->objs = NULL; + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_FLUSH); + cmd_p->resource_id = cpu_to_le32(resource_id); + cmd_p->r.width = cpu_to_le32(width); + cmd_p->r.height = cpu_to_le32(height); + cmd_p->r.x = cpu_to_le32(x); + cmd_p->r.y = cpu_to_le32(y); + + virtio_gpu_panic_queue_ctrl_buffer(vgdev, vbuf); +} + void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev, uint32_t resource_id, uint32_t x, uint32_t y, @@ -591,6 +711,37 @@ void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev, virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, fence); } +/* For drm_panic */ +int virtio_gpu_panic_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, + uint64_t offset, + uint32_t width, uint32_t height, + uint32_t x, uint32_t y, + struct virtio_gpu_object_array *objs) +{ + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]); + struct virtio_gpu_transfer_to_host_2d *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); + + if (virtio_gpu_is_shmem(bo) && use_dma_api) + dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, + bo->base.sgt, DMA_TO_DEVICE); + + cmd_p = virtio_gpu_panic_alloc_cmd_resp(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + vbuf->objs = objs; + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D); + cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle); + cmd_p->offset = cpu_to_le64(offset); + cmd_p->r.width = cpu_to_le32(width); + cmd_p->r.height = cpu_to_le32(height); + cmd_p->r.x = cpu_to_le32(x); + cmd_p->r.y = cpu_to_le32(y); + + return virtio_gpu_panic_queue_ctrl_buffer(vgdev, vbuf); +} + void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, uint64_t offset, uint32_t width, uint32_t height, -- cgit v1.2.3-59-g8ed1b From 4720e0ad30bbe87821e516e5c6cdeb94e615c6dd Mon Sep 17 00:00:00 2001 From: Andrzej Kacprowski Date: Tue, 4 Feb 2025 09:46:17 +0100 Subject: accel/ivpu: Add missing locks around mmu queues Multiple threads were accessing mmu cmd queue simultaneously causing sporadic failures in ivpu_mmu_cmdq_sync() function. Protect critical code with mmu mutex. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Andrzej Kacprowski Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250204084622.2422544-2-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_mmu.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index b80bdded9fd7..5ea010568faa 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -895,6 +895,9 @@ static int ivpu_mmu_evtq_disable(struct ivpu_device *vdev) void ivpu_mmu_discard_events(struct ivpu_device *vdev) { + struct ivpu_mmu_info *mmu = vdev->mmu; + + mutex_lock(&mmu->lock); /* * Disable event queue (stop MMU from updating the producer) * to allow synchronization of consumer and producer indexes @@ -908,6 +911,8 @@ void ivpu_mmu_discard_events(struct ivpu_device *vdev) ivpu_mmu_evtq_enable(vdev); drm_WARN_ON_ONCE(&vdev->drm, vdev->mmu->evtq.cons != vdev->mmu->evtq.prod); + + mutex_unlock(&mmu->lock); } int ivpu_mmu_disable_ssid_events(struct ivpu_device *vdev, u32 ssid) @@ -920,6 +925,8 @@ int ivpu_mmu_disable_ssid_events(struct ivpu_device *vdev, u32 ssid) if (ssid > IVPU_MMU_CDTAB_ENT_COUNT) return -EINVAL; + mutex_lock(&mmu->lock); + entry = cdtab->base + (ssid * IVPU_MMU_CDTAB_ENT_SIZE); val = READ_ONCE(entry[0]); @@ -932,6 +939,8 @@ int ivpu_mmu_disable_ssid_events(struct ivpu_device *vdev, u32 ssid) ivpu_mmu_cmdq_write_cfgi_all(vdev); ivpu_mmu_cmdq_sync(vdev); + mutex_unlock(&mmu->lock); + return 0; } -- cgit v1.2.3-59-g8ed1b From 7806bad76ac397a767f0c369534133c71c73b157 Mon Sep 17 00:00:00 2001 From: Andrzej Kacprowski Date: Tue, 4 Feb 2025 09:46:18 +0100 Subject: accel/ivpu: Prevent runtime suspend during context abort work Increment the runtime PM counter when entering ivpu_context_abort_work_fn() to prevent the device from suspending while the function is executing. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Andrzej Kacprowski Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250204084622.2422544-3-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_job.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index c1013f511efa..004059e4f1e8 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -965,6 +966,9 @@ void ivpu_context_abort_work_fn(struct work_struct *work) unsigned long ctx_id; unsigned long id; + if (drm_WARN_ON(&vdev->drm, pm_runtime_get_if_active(vdev->drm.dev) <= 0)) + return; + if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) ivpu_jsm_reset_engine(vdev, 0); @@ -987,7 +991,7 @@ void ivpu_context_abort_work_fn(struct work_struct *work) ivpu_mmu_discard_events(vdev); if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW) - return; + goto runtime_put; ivpu_jsm_hws_resume_engine(vdev, 0); /* @@ -1000,4 +1004,8 @@ void ivpu_context_abort_work_fn(struct work_struct *work) if (job->file_priv->aborted) ivpu_job_signal_and_destroy(vdev, job->job_id, DRM_IVPU_JOB_STATUS_ABORTED); mutex_unlock(&vdev->submitted_jobs_lock); + +runtime_put: + pm_runtime_mark_last_busy(vdev->drm.dev); + pm_runtime_put_autosuspend(vdev->drm.dev); } -- cgit v1.2.3-59-g8ed1b From 320323d2e5456df9d6236ac1ce9c030b1a74aa5b Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 4 Feb 2025 09:46:19 +0100 Subject: accel/ivpu: Add debugfs interface for setting HWS priority bands Add debugfs interface to modify following priority bands properties: * grace period * process grace period * process quantum This allows for the adjustment of hardware scheduling algorithm parameters for each existing priority band, facilitating validation and fine-tuning. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Karol Wachowski Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250204084622.2422544-4-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_debugfs.c | 84 +++++++++++++++++++++++++++++++++++++++ drivers/accel/ivpu/ivpu_hw.c | 21 ++++++++++ drivers/accel/ivpu/ivpu_hw.h | 5 +++ drivers/accel/ivpu/ivpu_jsm_msg.c | 29 +++++--------- 4 files changed, 121 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c index e79715c53f2a..0825851656a2 100644 --- a/drivers/accel/ivpu/ivpu_debugfs.c +++ b/drivers/accel/ivpu/ivpu_debugfs.c @@ -398,6 +398,88 @@ static int dct_active_set(void *data, u64 active_percent) DEFINE_DEBUGFS_ATTRIBUTE(ivpu_dct_fops, dct_active_get, dct_active_set, "%llu\n"); +static int priority_bands_show(struct seq_file *s, void *v) +{ + struct ivpu_device *vdev = s->private; + struct ivpu_hw_info *hw = vdev->hw; + + for (int band = VPU_JOB_SCHEDULING_PRIORITY_BAND_IDLE; + band < VPU_JOB_SCHEDULING_PRIORITY_BAND_COUNT; band++) { + switch (band) { + case VPU_JOB_SCHEDULING_PRIORITY_BAND_IDLE: + seq_puts(s, "Idle: "); + break; + + case VPU_JOB_SCHEDULING_PRIORITY_BAND_NORMAL: + seq_puts(s, "Normal: "); + break; + + case VPU_JOB_SCHEDULING_PRIORITY_BAND_FOCUS: + seq_puts(s, "Focus: "); + break; + + case VPU_JOB_SCHEDULING_PRIORITY_BAND_REALTIME: + seq_puts(s, "Realtime: "); + break; + } + + seq_printf(s, "grace_period %9u process_grace_period %9u process_quantum %9u\n", + hw->hws.grace_period[band], hw->hws.process_grace_period[band], + hw->hws.process_quantum[band]); + } + + return 0; +} + +static int priority_bands_fops_open(struct inode *inode, struct file *file) +{ + return single_open(file, priority_bands_show, inode->i_private); +} + +static ssize_t +priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) +{ + struct seq_file *s = file->private_data; + struct ivpu_device *vdev = s->private; + char buf[64]; + u32 grace_period; + u32 process_grace_period; + u32 process_quantum; + u32 band; + int ret; + + if (size >= sizeof(buf)) + return -EINVAL; + + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, pos, user_buf, size); + if (ret < 0) + return ret; + + buf[size] = '\0'; + ret = sscanf(buf, "%u %u %u %u", &band, &grace_period, &process_grace_period, + &process_quantum); + if (ret != 4) + return -EINVAL; + + if (band >= VPU_JOB_SCHEDULING_PRIORITY_BAND_COUNT) + return -EINVAL; + + vdev->hw->hws.grace_period[band] = grace_period; + vdev->hw->hws.process_grace_period[band] = process_grace_period; + vdev->hw->hws.process_quantum[band] = process_quantum; + + return size; +} + +static const struct file_operations ivpu_hws_priority_bands_fops = { + .owner = THIS_MODULE, + .open = priority_bands_fops_open, + .write = priority_bands_fops_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + void ivpu_debugfs_init(struct ivpu_device *vdev) { struct dentry *debugfs_root = vdev->drm.debugfs_root; @@ -420,6 +502,8 @@ void ivpu_debugfs_init(struct ivpu_device *vdev) &fw_trace_hw_comp_mask_fops); debugfs_create_file("fw_trace_level", 0200, debugfs_root, vdev, &fw_trace_level_fops); + debugfs_create_file("hws_priority_bands", 0200, debugfs_root, vdev, + &ivpu_hws_priority_bands_fops); debugfs_create_file("reset_engine", 0200, debugfs_root, vdev, &ivpu_reset_engine_fops); diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index 2057907c5aa6..f31702b3ecbd 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -113,6 +113,26 @@ static void timeouts_init(struct ivpu_device *vdev) } } +static void priority_bands_init(struct ivpu_device *vdev) +{ + /* Idle */ + vdev->hw->hws.grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_IDLE] = 0; + vdev->hw->hws.process_grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_IDLE] = 50000; + vdev->hw->hws.process_quantum[VPU_JOB_SCHEDULING_PRIORITY_BAND_IDLE] = 160000; + /* Normal */ + vdev->hw->hws.grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_NORMAL] = 50000; + vdev->hw->hws.process_grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_NORMAL] = 50000; + vdev->hw->hws.process_quantum[VPU_JOB_SCHEDULING_PRIORITY_BAND_NORMAL] = 300000; + /* Focus */ + vdev->hw->hws.grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_FOCUS] = 50000; + vdev->hw->hws.process_grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_FOCUS] = 50000; + vdev->hw->hws.process_quantum[VPU_JOB_SCHEDULING_PRIORITY_BAND_FOCUS] = 200000; + /* Realtime */ + vdev->hw->hws.grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_REALTIME] = 0; + vdev->hw->hws.process_grace_period[VPU_JOB_SCHEDULING_PRIORITY_BAND_REALTIME] = 50000; + vdev->hw->hws.process_quantum[VPU_JOB_SCHEDULING_PRIORITY_BAND_REALTIME] = 200000; +} + static void memory_ranges_init(struct ivpu_device *vdev) { if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { @@ -251,6 +271,7 @@ int ivpu_hw_init(struct ivpu_device *vdev) { ivpu_hw_btrs_info_init(vdev); ivpu_hw_btrs_freq_ratios_init(vdev); + priority_bands_init(vdev); memory_ranges_init(vdev); platform_init(vdev); wa_init(vdev); diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h index fbef9816b9d0..16435f2756d0 100644 --- a/drivers/accel/ivpu/ivpu_hw.h +++ b/drivers/accel/ivpu/ivpu_hw.h @@ -36,6 +36,11 @@ struct ivpu_hw_info { u8 pn_ratio; u32 profiling_freq; } pll; + struct { + u32 grace_period[VPU_HWS_NUM_PRIORITY_BANDS]; + u32 process_quantum[VPU_HWS_NUM_PRIORITY_BANDS]; + u32 process_grace_period[VPU_HWS_NUM_PRIORITY_BANDS]; + } hws; u32 tile_fuse; u32 sku; u16 config; diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.c b/drivers/accel/ivpu/ivpu_jsm_msg.c index 30a40be76930..219ab8afefab 100644 --- a/drivers/accel/ivpu/ivpu_jsm_msg.c +++ b/drivers/accel/ivpu/ivpu_jsm_msg.c @@ -7,6 +7,7 @@ #include "ivpu_hw.h" #include "ivpu_ipc.h" #include "ivpu_jsm_msg.h" +#include "vpu_jsm_api.h" const char *ivpu_jsm_msg_type_to_str(enum vpu_ipc_msg_type type) { @@ -407,26 +408,18 @@ int ivpu_jsm_hws_setup_priority_bands(struct ivpu_device *vdev) { struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP }; struct vpu_jsm_msg resp; + struct ivpu_hw_info *hw = vdev->hw; + struct vpu_ipc_msg_payload_hws_priority_band_setup *setup = + &req.payload.hws_priority_band_setup; int ret; - /* Idle */ - req.payload.hws_priority_band_setup.grace_period[0] = 0; - req.payload.hws_priority_band_setup.process_grace_period[0] = 50000; - req.payload.hws_priority_band_setup.process_quantum[0] = 160000; - /* Normal */ - req.payload.hws_priority_band_setup.grace_period[1] = 50000; - req.payload.hws_priority_band_setup.process_grace_period[1] = 50000; - req.payload.hws_priority_band_setup.process_quantum[1] = 300000; - /* Focus */ - req.payload.hws_priority_band_setup.grace_period[2] = 50000; - req.payload.hws_priority_band_setup.process_grace_period[2] = 50000; - req.payload.hws_priority_band_setup.process_quantum[2] = 200000; - /* Realtime */ - req.payload.hws_priority_band_setup.grace_period[3] = 0; - req.payload.hws_priority_band_setup.process_grace_period[3] = 50000; - req.payload.hws_priority_band_setup.process_quantum[3] = 200000; - - req.payload.hws_priority_band_setup.normal_band_percentage = 10; + for (int band = VPU_JOB_SCHEDULING_PRIORITY_BAND_IDLE; + band < VPU_JOB_SCHEDULING_PRIORITY_BAND_COUNT; band++) { + setup->grace_period[band] = hw->hws.grace_period[band]; + setup->process_grace_period[band] = hw->hws.process_grace_period[band]; + setup->process_quantum[band] = hw->hws.process_quantum[band]; + } + setup->normal_band_percentage = 10; ret = ivpu_ipc_send_receive_internal(vdev, &req, VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP_RSP, &resp, VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); -- cgit v1.2.3-59-g8ed1b From 67725f5e8d844e27db4514a76699ec6a7000c627 Mon Sep 17 00:00:00 2001 From: Tomasz Rusinowicz Date: Tue, 4 Feb 2025 09:46:20 +0100 Subject: accel/ivpu: Allow to import single buffer into multiple contexts Use ivpu_gem_prime_import() based on drm_gem_prime_import_dev() for importing buffers, removing optimization for same device imports. This optimization reused the same ivpu_bo object in multiple contexts but a single buffer can be MMU-mapped only to a single context. Each import now creates a new instance of ivpu_bo object that shares the same sg_table but have separate MMU mappings. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Tomasz Rusinowicz Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250204084622.2422544-5-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 2 +- drivers/accel/ivpu/ivpu_gem.c | 43 +++++++++++++++++++++++++++++++++++++++++++ drivers/accel/ivpu/ivpu_gem.h | 1 + 3 files changed, 45 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 6a80d626d609..f23e3e8ea9d8 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -452,7 +452,7 @@ static const struct drm_driver driver = { .postclose = ivpu_postclose, .gem_create_object = ivpu_gem_create_object, - .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table, + .gem_prime_import = ivpu_gem_prime_import, .ioctls = ivpu_drm_ioctls, .num_ioctls = ARRAY_SIZE(ivpu_drm_ioctls), diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c index 16178054e629..8741c73b92ce 100644 --- a/drivers/accel/ivpu/ivpu_gem.c +++ b/drivers/accel/ivpu/ivpu_gem.c @@ -20,6 +20,8 @@ #include "ivpu_mmu.h" #include "ivpu_mmu_context.h" +MODULE_IMPORT_NS("DMA_BUF"); + static const struct drm_gem_object_funcs ivpu_gem_funcs; static inline void ivpu_dbg_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, const char *action) @@ -172,6 +174,47 @@ struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t siz return &bo->base.base; } +struct drm_gem_object *ivpu_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf) +{ + struct device *attach_dev = dev->dev; + struct dma_buf_attachment *attach; + struct sg_table *sgt; + struct drm_gem_object *obj; + int ret; + + attach = dma_buf_attach(dma_buf, attach_dev); + if (IS_ERR(attach)) + return ERR_CAST(attach); + + get_dma_buf(dma_buf); + + sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto fail_detach; + } + + obj = drm_gem_shmem_prime_import_sg_table(dev, attach, sgt); + if (IS_ERR(obj)) { + ret = PTR_ERR(obj); + goto fail_unmap; + } + + obj->import_attach = attach; + obj->resv = dma_buf->resv; + + return obj; + +fail_unmap: + dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL); +fail_detach: + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); + + return ERR_PTR(ret); +} + static struct ivpu_bo *ivpu_bo_alloc(struct ivpu_device *vdev, u64 size, u32 flags) { struct drm_gem_shmem_object *shmem; diff --git a/drivers/accel/ivpu/ivpu_gem.h b/drivers/accel/ivpu/ivpu_gem.h index d975000abd78..a222a9ec9d61 100644 --- a/drivers/accel/ivpu/ivpu_gem.h +++ b/drivers/accel/ivpu/ivpu_gem.h @@ -28,6 +28,7 @@ int ivpu_bo_pin(struct ivpu_bo *bo); void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx); struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t size); +struct drm_gem_object *ivpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); struct ivpu_bo *ivpu_bo_create(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, struct ivpu_addr_range *range, u64 size, u32 flags); struct ivpu_bo *ivpu_bo_create_global(struct ivpu_device *vdev, u64 size, u32 flags); -- cgit v1.2.3-59-g8ed1b From 55e856c344b0473e78729e59e501b28d3c238b51 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 4 Feb 2025 09:46:21 +0100 Subject: accel/ivpu: Add test modes to toggle clock relinquish disable Add IVPU_TEST_MODE_CLK_RELINQ_[DISABLE|ENABLE] that overrides workaround for disabling clock relinquish for testing purposes. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Karol Wachowski Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250204084622.2422544-6-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.h | 2 ++ drivers/accel/ivpu/ivpu_hw.c | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index ca21102ca366..73d808068c8b 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -206,6 +206,8 @@ extern bool ivpu_force_snoop; #define IVPU_TEST_MODE_MIP_DISABLE BIT(6) #define IVPU_TEST_MODE_DISABLE_TIMEOUTS BIT(8) #define IVPU_TEST_MODE_TURBO BIT(9) +#define IVPU_TEST_MODE_CLK_RELINQ_DISABLE BIT(10) +#define IVPU_TEST_MODE_CLK_RELINQ_ENABLE BIT(11) extern int ivpu_test_mode; struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv); diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index f31702b3ecbd..4d9f30e3b505 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -68,6 +68,12 @@ static void wa_init(struct ivpu_device *vdev) ivpu_revision(vdev) < IVPU_HW_IP_REV_LNL_B0) vdev->wa.disable_clock_relinquish = true; + if (ivpu_test_mode & IVPU_TEST_MODE_CLK_RELINQ_ENABLE) + vdev->wa.disable_clock_relinquish = false; + + if (ivpu_test_mode & IVPU_TEST_MODE_CLK_RELINQ_DISABLE) + vdev->wa.disable_clock_relinquish = true; + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) vdev->wa.wp0_during_power_up = true; -- cgit v1.2.3-59-g8ed1b From 011529fe81121e2d343522ecbb149e9b2d1e5931 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Tue, 4 Feb 2025 09:46:22 +0100 Subject: accel/ivpu: Implement D0i2 disable test mode Add power_profile firmware boot param and set it to 0 by default which is default FW power profile. Implement IVPU_TEST_MODE_D0I2_DISABLE which is used for setting power profile boot param value to 1 which prevents NPU from entering d0i2 power state. Reviewed-by: Jacek Lawrynowicz Signed-off-by: Karol Wachowski Signed-off-by: Jacek Lawrynowicz Link: https://patchwork.freedesktop.org/patch/msgid/20250204084622.2422544-7-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.h | 2 ++ drivers/accel/ivpu/ivpu_fw.c | 4 ++++ drivers/accel/ivpu/ivpu_hw.c | 4 ++++ 3 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 73d808068c8b..92753effb1c9 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -111,6 +111,7 @@ struct ivpu_wa_table { bool disable_clock_relinquish; bool disable_d0i3_msg; bool wp0_during_power_up; + bool disable_d0i2; }; struct ivpu_hw_info; @@ -208,6 +209,7 @@ extern bool ivpu_force_snoop; #define IVPU_TEST_MODE_TURBO BIT(9) #define IVPU_TEST_MODE_CLK_RELINQ_DISABLE BIT(10) #define IVPU_TEST_MODE_CLK_RELINQ_ENABLE BIT(11) +#define IVPU_TEST_MODE_D0I2_DISABLE BIT(12) extern int ivpu_test_mode; struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv); diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index cfe8f79ec5a6..7a1bb92d8c81 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -534,6 +534,8 @@ static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_ boot_params->d0i3_entry_vpu_ts); ivpu_dbg(vdev, FW_BOOT, "boot_params.system_time_us = %llu\n", boot_params->system_time_us); + ivpu_dbg(vdev, FW_BOOT, "boot_params.power_profile = %u\n", + boot_params->power_profile); } void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *boot_params) @@ -634,6 +636,8 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params boot_params->d0i3_delayed_entry = 1; boot_params->d0i3_residency_time_us = 0; boot_params->d0i3_entry_vpu_ts = 0; + if (IVPU_WA(disable_d0i2)) + boot_params->power_profile = 1; boot_params->system_time_us = ktime_to_us(ktime_get_real()); wmb(); /* Flush WC buffers after writing bootparams */ diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c index 4d9f30e3b505..ec9a3629da3a 100644 --- a/drivers/accel/ivpu/ivpu_hw.c +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -77,11 +77,15 @@ static void wa_init(struct ivpu_device *vdev) if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) vdev->wa.wp0_during_power_up = true; + if (ivpu_test_mode & IVPU_TEST_MODE_D0I2_DISABLE) + vdev->wa.disable_d0i2 = true; + IVPU_PRINT_WA(punit_disabled); IVPU_PRINT_WA(clear_runtime_mem); IVPU_PRINT_WA(interrupt_clear_with_0); IVPU_PRINT_WA(disable_clock_relinquish); IVPU_PRINT_WA(wp0_during_power_up); + IVPU_PRINT_WA(disable_d0i2); } static void timeouts_init(struct ivpu_device *vdev) -- cgit v1.2.3-59-g8ed1b From cbc0a0ee34b5f108b184a6d59afd0f305564350a Mon Sep 17 00:00:00 2001 From: Piotr Piórkowski Date: Fri, 7 Feb 2025 12:31:11 +0100 Subject: drm/xe/pf: Use an explicit check to see if the device has LMTT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far, the main condition for using LMTT has been to check that the device is a discrete gfx. Let's add a dedicated function to check if the device supports LMTT as not all future discrete GPU platforms will require LMTT. v2: - use xe_has_device_lmtt only when necessary - leave IS_DGFX for other things related to LMEM provisioning v3: - remove IS_SRIOV_PF condition from xe_device_has_lmtt (Michal Wajdeczko) - keep IS_SRIOV_PF asserts in LMTT-related code (Michal Wajdeczko) v4: - update commit description Signed-off-by: Piotr Piórkowski Cc: Michal Wajdeczko Cc: Michał Winiarski Cc: Satyanarayana K V P Reviewed-by: Tejas Upadhyay Reviewed-by: Satyanarayana K V P Signed-off-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20250207113111.853821-2-piotr.piorkowski@intel.com --- drivers/gpu/drm/xe/xe_device.h | 5 +++++ drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 21 +++++++++++++-------- drivers/gpu/drm/xe/xe_lmtt.c | 4 ++-- 3 files changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index fc3c2af3fb7f..0bc3bc8e6803 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -170,6 +170,11 @@ static inline bool xe_device_uses_memirq(struct xe_device *xe) return xe_device_has_memirq(xe) && (IS_SRIOV_VF(xe) || xe_device_has_msix(xe)); } +static inline bool xe_device_has_lmtt(struct xe_device *xe) +{ + return IS_DGFX(xe); +} + u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size); void xe_device_snapshot_print(struct xe_device *xe, struct drm_printer *p); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index b1d994d65589..5c3e9e5bd051 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1336,7 +1336,7 @@ static void pf_reset_vf_lmtt(struct xe_device *xe, unsigned int vfid) struct xe_tile *tile; unsigned int tid; - xe_assert(xe, IS_DGFX(xe)); + xe_assert(xe, xe_device_has_lmtt(xe)); xe_assert(xe, IS_SRIOV_PF(xe)); for_each_tile(tile, xe, tid) { @@ -1357,7 +1357,7 @@ static int pf_update_vf_lmtt(struct xe_device *xe, unsigned int vfid) unsigned int tid; int err; - xe_assert(xe, IS_DGFX(xe)); + xe_assert(xe, xe_device_has_lmtt(xe)); xe_assert(xe, IS_SRIOV_PF(xe)); total = 0; @@ -1434,7 +1434,8 @@ static int pf_provision_vf_lmem(struct xe_gt *gt, unsigned int vfid, u64 size) if (unlikely(err)) return err; - pf_reset_vf_lmtt(xe, vfid); + if (xe_device_has_lmtt(xe)) + pf_reset_vf_lmtt(xe, vfid); pf_release_vf_config_lmem(gt, config); } xe_gt_assert(gt, !config->lmem_obj); @@ -1454,9 +1455,11 @@ static int pf_provision_vf_lmem(struct xe_gt *gt, unsigned int vfid, u64 size) config->lmem_obj = bo; - err = pf_update_vf_lmtt(xe, vfid); - if (unlikely(err)) - goto release; + if (xe_device_has_lmtt(xe)) { + err = pf_update_vf_lmtt(xe, vfid); + if (unlikely(err)) + goto release; + } err = pf_push_vf_cfg_lmem(gt, vfid, bo->size); if (unlikely(err)) @@ -1467,7 +1470,8 @@ static int pf_provision_vf_lmem(struct xe_gt *gt, unsigned int vfid, u64 size) return 0; reset_lmtt: - pf_reset_vf_lmtt(xe, vfid); + if (xe_device_has_lmtt(xe)) + pf_reset_vf_lmtt(xe, vfid); release: pf_release_vf_config_lmem(gt, config); return err; @@ -1981,7 +1985,8 @@ static void pf_release_vf_config(struct xe_gt *gt, unsigned int vfid) pf_release_vf_config_ggtt(gt, config); if (IS_DGFX(xe)) { pf_release_vf_config_lmem(gt, config); - pf_update_vf_lmtt(xe, vfid); + if (xe_device_has_lmtt(xe)) + pf_update_vf_lmtt(xe, vfid); } } pf_release_config_ctxs(gt, config); diff --git a/drivers/gpu/drm/xe/xe_lmtt.c b/drivers/gpu/drm/xe/xe_lmtt.c index a60ceae4c6dd..89393dcb53d9 100644 --- a/drivers/gpu/drm/xe/xe_lmtt.c +++ b/drivers/gpu/drm/xe/xe_lmtt.c @@ -164,7 +164,7 @@ int xe_lmtt_init(struct xe_lmtt *lmtt) lmtt_assert(lmtt, IS_SRIOV_PF(xe)); lmtt_assert(lmtt, !lmtt->ops); - if (!IS_DGFX(xe)) + if (!xe_device_has_lmtt(xe)) return 0; if (xe_has_multi_level_lmtt(xe)) @@ -486,7 +486,7 @@ u64 xe_lmtt_estimate_pt_size(struct xe_lmtt *lmtt, u64 size) u64 pt_size; lmtt_assert(lmtt, IS_SRIOV_PF(lmtt_to_xe(lmtt))); - lmtt_assert(lmtt, IS_DGFX(lmtt_to_xe(lmtt))); + lmtt_assert(lmtt, xe_device_has_lmtt(lmtt_to_xe(lmtt))); lmtt_assert(lmtt, lmtt->ops); pt_size = PAGE_ALIGN(lmtt->ops->lmtt_pte_size(level) * -- cgit v1.2.3-59-g8ed1b From 2c569b955e02d06c97fa23b6fa367583e4fca1c8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 7 Feb 2025 12:41:10 +0200 Subject: drm/i915/hdcp: Move HDCP debugfs to intel_hdcp.c Continue with placing debugfs next to the implementation. intel_connector_info() still needs intel_hdcp_info(), so we'll need to expose that too. Cc: Suraj Kandpal Reviewed-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/c118e992673f6b054aacaff0e1850fcea329e000.1738924826.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_debugfs.c | 74 +------------------ drivers/gpu/drm/i915/display/intel_hdcp.c | 82 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_hdcp.h | 4 ++ 3 files changed, 88 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 926f09c35084..e547ea66657d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -213,38 +213,6 @@ static void intel_panel_info(struct seq_file *m, intel_seq_print_mode(m, 2, fixed_mode); } -static void intel_hdcp_info(struct seq_file *m, - struct intel_connector *intel_connector, - bool remote_req) -{ - bool hdcp_cap = false, hdcp2_cap = false; - - if (!intel_connector->hdcp.shim) { - seq_puts(m, "No Connector Support"); - goto out; - } - - if (remote_req) { - intel_hdcp_get_remote_capability(intel_connector, - &hdcp_cap, - &hdcp2_cap); - } else { - hdcp_cap = intel_hdcp_get_capability(intel_connector); - hdcp2_cap = intel_hdcp2_get_capability(intel_connector); - } - - if (hdcp_cap) - seq_puts(m, "HDCP1.4 "); - if (hdcp2_cap) - seq_puts(m, "HDCP2.2 "); - - if (!hdcp_cap && !hdcp2_cap) - seq_puts(m, "None"); - -out: - seq_puts(m, "\n"); -} - static void intel_dp_info(struct seq_file *m, struct intel_connector *connector) { struct intel_encoder *intel_encoder = intel_attached_encoder(connector); @@ -309,12 +277,7 @@ static void intel_connector_info(struct seq_file *m, break; } - seq_puts(m, "\tHDCP version: "); - if (intel_connector->mst_port) { - intel_hdcp_info(m, intel_connector, true); - seq_puts(m, "\tMST Hub HDCP version: "); - } - intel_hdcp_info(m, intel_connector, false); + intel_hdcp_info(m, intel_connector); seq_printf(m, "\tmax bpc: %u\n", connector->display_info.bpc); @@ -893,33 +856,6 @@ void intel_display_debugfs_register(struct drm_i915_private *i915) intel_display_debugfs_params(display); } -static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data) -{ - struct intel_connector *connector = m->private; - struct drm_i915_private *i915 = to_i915(connector->base.dev); - int ret; - - ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); - if (ret) - return ret; - - if (!connector->base.encoder || - connector->base.status != connector_status_connected) { - ret = -ENODEV; - goto out; - } - - seq_printf(m, "%s:%d HDCP version: ", connector->base.name, - connector->base.base.id); - intel_hdcp_info(m, connector, false); - -out: - drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); - - return ret; -} -DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability); - static int i915_lpsp_capability_show(struct seq_file *m, void *data) { struct intel_connector *connector = m->private; @@ -1401,18 +1337,12 @@ void intel_connector_debugfs_add(struct intel_connector *connector) return; intel_drrs_connector_debugfs_add(connector); + intel_hdcp_connector_debugfs_add(connector); intel_pps_connector_debugfs_add(connector); intel_psr_connector_debugfs_add(connector); intel_alpm_lobf_debugfs_add(connector); intel_dp_link_training_debugfs_add(connector); - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || - connector_type == DRM_MODE_CONNECTOR_HDMIA || - connector_type == DRM_MODE_CONNECTOR_HDMIB) { - debugfs_create_file("i915_hdcp_sink_capability", 0444, root, - connector, &i915_hdcp_sink_capability_fops); - } - if (DISPLAY_VER(i915) >= 11 && ((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !connector->mst_port) || connector_type == DRM_MODE_CONNECTOR_eDP)) { diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 7cc0399b2a5d..718d8bad77a0 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -9,6 +9,7 @@ */ #include +#include #include #include @@ -2731,3 +2732,84 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector) queue_delayed_work(i915->unordered_wq, &hdcp->check_work, 0); } + +static void __intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector, + bool remote_req) +{ + bool hdcp_cap = false, hdcp2_cap = false; + + if (!intel_connector->hdcp.shim) { + seq_puts(m, "No Connector Support"); + goto out; + } + + if (remote_req) { + intel_hdcp_get_remote_capability(intel_connector, + &hdcp_cap, + &hdcp2_cap); + } else { + hdcp_cap = intel_hdcp_get_capability(intel_connector); + hdcp2_cap = intel_hdcp2_get_capability(intel_connector); + } + + if (hdcp_cap) + seq_puts(m, "HDCP1.4 "); + if (hdcp2_cap) + seq_puts(m, "HDCP2.2 "); + + if (!hdcp_cap && !hdcp2_cap) + seq_puts(m, "None"); + +out: + seq_puts(m, "\n"); +} + +void intel_hdcp_info(struct seq_file *m, struct intel_connector *connector) +{ + seq_puts(m, "\tHDCP version: "); + if (connector->mst_port) { + __intel_hdcp_info(m, connector, true); + seq_puts(m, "\tMST Hub HDCP version: "); + } + __intel_hdcp_info(m, connector, false); +} + +static int intel_hdcp_sink_capability_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = m->private; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; + + ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (ret) + return ret; + + if (!connector->base.encoder || + connector->base.status != connector_status_connected) { + ret = -ENODEV; + goto out; + } + + seq_printf(m, "%s:%d HDCP version: ", connector->base.name, + connector->base.base.id); + __intel_hdcp_info(m, connector, false); + +out: + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return ret; +} +DEFINE_SHOW_ATTRIBUTE(intel_hdcp_sink_capability); + +void intel_hdcp_connector_debugfs_add(struct intel_connector *connector) +{ + struct dentry *root = connector->base.debugfs_entry; + int connector_type = connector->base.connector_type; + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector_type == DRM_MODE_CONNECTOR_HDMIB) { + debugfs_create_file("i915_hdcp_sink_capability", 0444, root, + connector, &intel_hdcp_sink_capability_fops); + } +} diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index d99830cfb798..76bd3996f636 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -19,6 +19,7 @@ struct intel_digital_port; struct intel_display; struct intel_encoder; struct intel_hdcp_shim; +struct seq_file; enum port; enum transcoder; @@ -48,4 +49,7 @@ void intel_hdcp_component_fini(struct intel_display *display); void intel_hdcp_cleanup(struct intel_connector *connector); void intel_hdcp_handle_cp_irq(struct intel_connector *connector); +void intel_hdcp_info(struct seq_file *m, struct intel_connector *connector); +void intel_hdcp_connector_debugfs_add(struct intel_connector *connector); + #endif /* __INTEL_HDCP_H__ */ -- cgit v1.2.3-59-g8ed1b From 3a178c1a23ee9841722a898a8245f1a9429b65e5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 7 Feb 2025 12:41:11 +0200 Subject: drm/i915/hdcp: rename intel_connector to connector Follow the current convention of naming struct intel_connector pointers connector. Cc: Suraj Kandpal Reviewed-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/8f43542a8f0ce0ec5725b769c077d3cea723bde0.1738924826.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdcp.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 718d8bad77a0..9880192adfe9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2733,23 +2733,21 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector) queue_delayed_work(i915->unordered_wq, &hdcp->check_work, 0); } -static void __intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector, +static void __intel_hdcp_info(struct seq_file *m, struct intel_connector *connector, bool remote_req) { bool hdcp_cap = false, hdcp2_cap = false; - if (!intel_connector->hdcp.shim) { + if (!connector->hdcp.shim) { seq_puts(m, "No Connector Support"); goto out; } if (remote_req) { - intel_hdcp_get_remote_capability(intel_connector, - &hdcp_cap, - &hdcp2_cap); + intel_hdcp_get_remote_capability(connector, &hdcp_cap, &hdcp2_cap); } else { - hdcp_cap = intel_hdcp_get_capability(intel_connector); - hdcp2_cap = intel_hdcp2_get_capability(intel_connector); + hdcp_cap = intel_hdcp_get_capability(connector); + hdcp2_cap = intel_hdcp2_get_capability(connector); } if (hdcp_cap) -- cgit v1.2.3-59-g8ed1b From d4e51a45f1964b50fac8e1ae8cc12aaa8dd8c87d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 7 Feb 2025 12:41:12 +0200 Subject: drm/i915/hdcp: Convert platform checks to use display->platform Prefer display->platform. over IS_(i915), and reducate struct drm_i915_private usages while at it. Cc: Suraj Kandpal Reviewed-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/58bad1e888a57a014acbaae67ccddd4f895091a7.1738924826.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdcp.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 9880192adfe9..3d83db793baf 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -343,7 +343,7 @@ static bool hdcp_key_loadable(struct intel_display *display) * On HSW and BDW, Display HW loads the Key as soon as Display resumes. * On all BXT+, SW can load the keys only when the PW#1 is turned on. */ - if (IS_HASWELL(i915) || IS_BROADWELL(i915)) + if (display->platform.haswell || display->platform.broadwell) id = HSW_DISP_PW_GLOBAL; else id = SKL_DISP_PW_1; @@ -382,7 +382,7 @@ static int intel_hdcp_load_keys(struct intel_display *display) * On HSW and BDW HW loads the HDCP1.4 Key when Display comes * out of reset. So if Key is not already loaded, its an error state. */ - if (IS_HASWELL(i915) || IS_BROADWELL(i915)) + if (display->platform.haswell || display->platform.broadwell) if (!(intel_de_read(display, HDCP_KEY_STATUS) & HDCP_KEY_LOAD_DONE)) return -ENXIO; @@ -394,7 +394,7 @@ static int intel_hdcp_load_keys(struct intel_display *display) * process from other platforms. These platforms use the GT Driver * Mailbox interface. */ - if (DISPLAY_VER(display) == 9 && !IS_BROXTON(i915)) { + if (DISPLAY_VER(display) == 9 && !display->platform.broxton) { ret = snb_pcode_write(&i915->uncore, SKL_PCODE_LOAD_HDCP_KEYS, 1); if (ret) { drm_err(display->drm, @@ -2339,18 +2339,16 @@ static int initialize_hdcp_port_data(struct intel_connector *connector, static bool is_hdcp2_supported(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - if (intel_hdcp_gsc_cs_required(display)) return true; if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP)) return false; - return (DISPLAY_VER(display) >= 10 || - IS_KABYLAKE(i915) || - IS_COFFEELAKE(i915) || - IS_COMETLAKE(i915)); + return DISPLAY_VER(display) >= 10 || + display->platform.kabylake || + display->platform.coffeelake || + display->platform.cometlake; } void intel_hdcp_component_init(struct intel_display *display) @@ -2775,10 +2773,10 @@ void intel_hdcp_info(struct seq_file *m, struct intel_connector *connector) static int intel_hdcp_sink_capability_show(struct seq_file *m, void *data) { struct intel_connector *connector = m->private; - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); int ret; - ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + ret = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex); if (ret) return ret; @@ -2793,7 +2791,7 @@ static int intel_hdcp_sink_capability_show(struct seq_file *m, void *data) __intel_hdcp_info(m, connector, false); out: - drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + drm_modeset_unlock(&display->drm->mode_config.connection_mutex); return ret; } -- cgit v1.2.3-59-g8ed1b From 7d94a9a1c461674df3fc17ed31a05de6eae63263 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 7 Feb 2025 12:58:38 +0200 Subject: drm/i915/hdcp: Make some functions static With the debugfs implementation moved next to the implementation, we no longer need to expose some of the functions. Make them static. Cc: Suraj Kandpal Reviewed-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/20250207105838.179805-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdcp.c | 10 +++++----- drivers/gpu/drm/i915/display/intel_hdcp.h | 6 ------ 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 3d83db793baf..1aa4c0fd216f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -209,7 +209,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_get_capability(struct intel_connector *connector) +static bool intel_hdcp_get_capability(struct intel_connector *connector) { struct intel_digital_port *dig_port; const struct intel_hdcp_shim *shim = connector->hdcp.shim; @@ -265,7 +265,7 @@ static bool intel_hdcp2_prerequisite(struct intel_connector *connector) } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_get_capability(struct intel_connector *connector) +static bool intel_hdcp2_get_capability(struct intel_connector *connector) { struct intel_hdcp *hdcp = &connector->hdcp; bool capable = false; @@ -279,9 +279,9 @@ bool intel_hdcp2_get_capability(struct intel_connector *connector) return capable; } -void intel_hdcp_get_remote_capability(struct intel_connector *connector, - bool *hdcp_capable, - bool *hdcp2_capable) +static void intel_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable) { struct intel_hdcp *hdcp = &connector->hdcp; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index 76bd3996f636..3a7905551051 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -21,7 +21,6 @@ struct intel_encoder; struct intel_hdcp_shim; struct seq_file; enum port; -enum transcoder; void intel_hdcp_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, @@ -39,11 +38,6 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); bool is_hdcp_supported(struct intel_display *display, enum port port); -bool intel_hdcp_get_capability(struct intel_connector *connector); -bool intel_hdcp2_get_capability(struct intel_connector *connector); -void intel_hdcp_get_remote_capability(struct intel_connector *connector, - bool *hdcp_capable, - bool *hdcp2_capable); void intel_hdcp_component_init(struct intel_display *display); void intel_hdcp_component_fini(struct intel_display *display); void intel_hdcp_cleanup(struct intel_connector *connector); -- cgit v1.2.3-59-g8ed1b From fc3a50c12ebd33c77b7e4a1e4f154a44315d3169 Mon Sep 17 00:00:00 2001 From: Piotr Piórkowski Date: Mon, 10 Feb 2025 09:15:10 +0100 Subject: drm/xe: Rename struct xe_mem_region to struct xe_vram_region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xe_mem_region structure has so far been used only in the context of VRAM regions. Also, the description of its fields clearly indicates that it was designed for VRAM regions. This struct is strictly related only to VRAM. So let's be clear on this point and rename it to xe_vram_region. Signed-off-by: Piotr Piórkowski Reviewed-by: Rodrigo Vivi Signed-off-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20250210081511.906452-2-piotr.piorkowski@intel.com --- drivers/gpu/drm/xe/xe_bo.c | 12 ++++++------ drivers/gpu/drm/xe/xe_device_types.h | 8 ++++---- drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 2 +- drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 6812164e1470..a202d5525822 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -143,7 +143,7 @@ mem_type_to_migrate(struct xe_device *xe, u32 mem_type) return tile->migrate; } -static struct xe_mem_region *res_to_mem_region(struct ttm_resource *res) +static struct xe_vram_region *res_to_mem_region(struct ttm_resource *res) { struct xe_device *xe = ttm_to_xe_device(res->bo->bdev); struct ttm_resource_manager *mgr; @@ -179,7 +179,7 @@ static void add_vram(struct xe_device *xe, struct xe_bo *bo, struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c) { struct ttm_place place = { .mem_type = mem_type }; - struct xe_mem_region *vram; + struct xe_vram_region *vram; u64 io_size; xe_assert(xe, *c < ARRAY_SIZE(bo->placements)); @@ -468,7 +468,7 @@ static int xe_ttm_io_mem_reserve(struct ttm_device *bdev, return 0; case XE_PL_VRAM0: case XE_PL_VRAM1: { - struct xe_mem_region *vram = res_to_mem_region(mem); + struct xe_vram_region *vram = res_to_mem_region(mem); if (!xe_ttm_resource_visible(mem)) return -EINVAL; @@ -815,7 +815,7 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, /* Create a new VMAP once kernel BO back in VRAM */ if (!ret && resource_is_vram(new_mem)) { - struct xe_mem_region *vram = res_to_mem_region(new_mem); + struct xe_vram_region *vram = res_to_mem_region(new_mem); void __iomem *new_addr = vram->mapping + (new_mem->start << PAGE_SHIFT); @@ -1025,7 +1025,7 @@ static unsigned long xe_ttm_io_mem_pfn(struct ttm_buffer_object *ttm_bo, { struct xe_bo *bo = ttm_to_xe_bo(ttm_bo); struct xe_res_cursor cursor; - struct xe_mem_region *vram; + struct xe_vram_region *vram; if (ttm_bo->resource->mem_type == XE_PL_STOLEN) return xe_ttm_stolen_io_offset(bo, page_offset << PAGE_SHIFT) >> PAGE_SHIFT; @@ -1165,7 +1165,7 @@ static int xe_ttm_access_memory(struct ttm_buffer_object *ttm_bo, struct xe_device *xe = ttm_to_xe_device(ttm_bo->bdev); struct iosys_map vmap; struct xe_res_cursor cursor; - struct xe_mem_region *vram; + struct xe_vram_region *vram; int bytes_left = len; xe_bo_assert_held(bo); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index c0e886bac183..1f27ed2c0448 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -70,11 +70,11 @@ struct xe_pxp; struct xe_tile * : (tile__)->xe) /** - * struct xe_mem_region - memory region structure + * struct xe_vram_region - memory region structure * This is used to describe a memory region in xe * device, such as HBM memory or CXL extension memory. */ -struct xe_mem_region { +struct xe_vram_region { /** @io_start: IO start address of this VRAM instance */ resource_size_t io_start; /** @@ -197,7 +197,7 @@ struct xe_tile { * Although VRAM is associated with a specific tile, it can * still be accessed by all tiles' GTs. */ - struct xe_mem_region vram; + struct xe_vram_region vram; /** @mem.vram_mgr: VRAM TTM manager */ struct xe_ttm_vram_mgr *vram_mgr; @@ -369,7 +369,7 @@ struct xe_device { /** @mem: memory info for device */ struct { /** @mem.vram: VRAM info for device */ - struct xe_mem_region vram; + struct xe_vram_region vram; /** @mem.sys_mgr: system TTM manager */ struct ttm_resource_manager sys_mgr; } mem; diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c index f4a16e5fa770..a8c37fb4fec0 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c @@ -340,7 +340,7 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr, int xe_ttm_vram_mgr_init(struct xe_tile *tile, struct xe_ttm_vram_mgr *mgr) { struct xe_device *xe = tile_to_xe(tile); - struct xe_mem_region *vram = &tile->mem.vram; + struct xe_vram_region *vram = &tile->mem.vram; mgr->vram = vram; return __xe_ttm_vram_mgr_init(xe, mgr, XE_PL_VRAM0 + tile->id, diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h index 2d75cf126289..4c52ced4ee44 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h @@ -9,7 +9,7 @@ #include #include -struct xe_mem_region; +struct xe_vram_region; /** * struct xe_ttm_vram_mgr - XE TTM VRAM manager @@ -22,7 +22,7 @@ struct xe_ttm_vram_mgr { /** @mm: DRM buddy allocator which manages the VRAM */ struct drm_buddy mm; /** @vram: ptr to details of associated VRAM region */ - struct xe_mem_region *vram; + struct xe_vram_region *vram; /** @visible_size: Proped size of the CPU visible portion */ u64 visible_size; /** @visible_avail: CPU visible portion still unallocated */ -- cgit v1.2.3-59-g8ed1b From 71163271dc227f8dd0d9446b8897a141c2eae957 Mon Sep 17 00:00:00 2001 From: Piotr Piórkowski Date: Mon, 10 Feb 2025 09:15:11 +0100 Subject: drm/xe: Move VRAM manager to struct xe_vram_region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VRAM manager is related directly to struct xe_vram_region so it should be inside this structure. Let's move the VRAM to struct xe_vram_region. v2: - remove xe_vram_region pointer from xe_ttm_vram_mgr - stop use dynamic alloaction for xe_ttm_vram_mgr in xe_vram_region - rename struct xe_ttm_vram_mgr vram_mgr to ttm v3: - fix "'ttm' not described in 'xe_vram_region'" Signed-off-by: Piotr Piórkowski Cc: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20250210081511.906452-3-piotr.piorkowski@intel.com --- drivers/gpu/drm/xe/xe_bo.c | 10 ++++++++-- drivers/gpu/drm/xe/xe_device_types.h | 6 +++--- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 2 +- drivers/gpu/drm/xe/xe_tile.c | 6 +----- drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 1 - drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 4 ---- 6 files changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index a202d5525822..78d09c5ed26d 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -147,10 +147,13 @@ static struct xe_vram_region *res_to_mem_region(struct ttm_resource *res) { struct xe_device *xe = ttm_to_xe_device(res->bo->bdev); struct ttm_resource_manager *mgr; + struct xe_ttm_vram_mgr *vram_mgr; xe_assert(xe, resource_is_vram(res)); mgr = ttm_manager_type(&xe->ttm, res->mem_type); - return to_xe_ttm_vram_mgr(mgr)->vram; + vram_mgr = to_xe_ttm_vram_mgr(mgr); + + return container_of(vram_mgr, struct xe_vram_region, ttm); } static void try_add_system(struct xe_device *xe, struct xe_bo *bo, @@ -179,12 +182,15 @@ static void add_vram(struct xe_device *xe, struct xe_bo *bo, struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c) { struct ttm_place place = { .mem_type = mem_type }; + struct ttm_resource_manager *mgr = ttm_manager_type(&xe->ttm, mem_type); + struct xe_ttm_vram_mgr *vram_mgr = to_xe_ttm_vram_mgr(mgr); + struct xe_vram_region *vram; u64 io_size; xe_assert(xe, *c < ARRAY_SIZE(bo->placements)); - vram = to_xe_ttm_vram_mgr(ttm_manager_type(&xe->ttm, mem_type))->vram; + vram = container_of(vram_mgr, struct xe_vram_region, ttm); xe_assert(xe, vram && vram->usable_size); io_size = vram->io_size; diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 1f27ed2c0448..28d10a1d7b64 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -23,6 +23,7 @@ #include "xe_sriov_types.h" #include "xe_step_types.h" #include "xe_survivability_mode_types.h" +#include "xe_ttm_vram_mgr_types.h" #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) #define TEST_VM_OPS_ERROR @@ -105,6 +106,8 @@ struct xe_vram_region { resource_size_t actual_physical_size; /** @mapping: pointer to VRAM mappable space */ void __iomem *mapping; + /** @ttm: VRAM TTM manager */ + struct xe_ttm_vram_mgr ttm; }; /** @@ -199,9 +202,6 @@ struct xe_tile { */ struct xe_vram_region vram; - /** @mem.vram_mgr: VRAM TTM manager */ - struct xe_ttm_vram_mgr *vram_mgr; - /** @mem.ggtt: Global graphics translation table */ struct xe_ggtt *ggtt; diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 5c3e9e5bd051..88bd9d97ba5c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1564,7 +1564,7 @@ static u64 pf_query_free_lmem(struct xe_gt *gt) { struct xe_tile *tile = gt->tile; - return xe_ttm_vram_get_avail(&tile->mem.vram_mgr->manager); + return xe_ttm_vram_get_avail(&tile->mem.vram.ttm.manager); } static u64 pf_query_max_lmem(struct xe_gt *gt) diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c index 2825553b568f..d9a7a04ff652 100644 --- a/drivers/gpu/drm/xe/xe_tile.c +++ b/drivers/gpu/drm/xe/xe_tile.c @@ -94,10 +94,6 @@ static int xe_tile_alloc(struct xe_tile *tile) return -ENOMEM; tile->mem.ggtt->tile = tile; - tile->mem.vram_mgr = drmm_kzalloc(drm, sizeof(*tile->mem.vram_mgr), GFP_KERNEL); - if (!tile->mem.vram_mgr) - return -ENOMEM; - return 0; } @@ -139,7 +135,7 @@ static int tile_ttm_mgr_init(struct xe_tile *tile) int err; if (tile->mem.vram.usable_size) { - err = xe_ttm_vram_mgr_init(tile, tile->mem.vram_mgr); + err = xe_ttm_vram_mgr_init(tile, &tile->mem.vram.ttm); if (err) return err; xe->info.mem_region_mask |= BIT(tile->id) << 1; diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c index a8c37fb4fec0..9e375a40aee9 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c @@ -342,7 +342,6 @@ int xe_ttm_vram_mgr_init(struct xe_tile *tile, struct xe_ttm_vram_mgr *mgr) struct xe_device *xe = tile_to_xe(tile); struct xe_vram_region *vram = &tile->mem.vram; - mgr->vram = vram; return __xe_ttm_vram_mgr_init(xe, mgr, XE_PL_VRAM0 + tile->id, vram->usable_size, vram->io_size, PAGE_SIZE); diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h index 4c52ced4ee44..1144f9232ebb 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h @@ -9,8 +9,6 @@ #include #include -struct xe_vram_region; - /** * struct xe_ttm_vram_mgr - XE TTM VRAM manager * @@ -21,8 +19,6 @@ struct xe_ttm_vram_mgr { struct ttm_resource_manager manager; /** @mm: DRM buddy allocator which manages the VRAM */ struct drm_buddy mm; - /** @vram: ptr to details of associated VRAM region */ - struct xe_vram_region *vram; /** @visible_size: Proped size of the CPU visible portion */ u64 visible_size; /** @visible_avail: CPU visible portion still unallocated */ -- cgit v1.2.3-59-g8ed1b From 0678c15b942770223ec339ed58c79303d1b991ec Mon Sep 17 00:00:00 2001 From: Zhaoyu Liu Date: Sun, 26 Jan 2025 17:32:56 +0800 Subject: drm/ttm: use ttm_resource_unevictable() to replace pin_count and swapped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TTM always uses pin_count and ttm_resource_is_swapped() together to determine whether a BO is unevictable. Now use ttm_resource_unevictable() to replace them. Signed-off-by: Zhaoyu Liu Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20250126093256.GA688734@bytedance Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_resource.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 1644beb7a745..7e5a60c55813 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -269,11 +269,16 @@ static bool ttm_resource_is_swapped(struct ttm_resource *res, struct ttm_buffer_ return ttm_tt_is_swapped(bo->ttm); } +static bool ttm_resource_unevictable(struct ttm_resource *res, struct ttm_buffer_object *bo) +{ + return bo->pin_count || ttm_resource_is_swapped(res, bo); +} + /* Add the resource to a bulk move if the BO is configured for it */ void ttm_resource_add_bulk_move(struct ttm_resource *res, struct ttm_buffer_object *bo) { - if (bo->bulk_move && !bo->pin_count && !ttm_resource_is_swapped(res, bo)) + if (bo->bulk_move && !ttm_resource_unevictable(res, bo)) ttm_lru_bulk_move_add(bo->bulk_move, res); } @@ -281,7 +286,7 @@ void ttm_resource_add_bulk_move(struct ttm_resource *res, void ttm_resource_del_bulk_move(struct ttm_resource *res, struct ttm_buffer_object *bo) { - if (bo->bulk_move && !bo->pin_count && !ttm_resource_is_swapped(res, bo)) + if (bo->bulk_move && !ttm_resource_unevictable(res, bo)) ttm_lru_bulk_move_del(bo->bulk_move, res); } @@ -293,10 +298,10 @@ void ttm_resource_move_to_lru_tail(struct ttm_resource *res) lockdep_assert_held(&bo->bdev->lru_lock); - if (bo->pin_count || ttm_resource_is_swapped(res, bo)) { + if (ttm_resource_unevictable(res, bo)) { list_move_tail(&res->lru.link, &bdev->unevictable); - } else if (bo->bulk_move) { + } else if (bo->bulk_move) { struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bo->bulk_move, res); @@ -335,7 +340,7 @@ void ttm_resource_init(struct ttm_buffer_object *bo, man = ttm_manager_type(bo->bdev, place->mem_type); spin_lock(&bo->bdev->lru_lock); - if (bo->pin_count || ttm_resource_is_swapped(res, bo)) + if (ttm_resource_unevictable(res, bo)) list_add_tail(&res->lru.link, &bo->bdev->unevictable); else list_add_tail(&res->lru.link, &man->lru[bo->priority]); -- cgit v1.2.3-59-g8ed1b From aaad45cfaa1bdb774e3755c93c0ab5ef6858917a Mon Sep 17 00:00:00 2001 From: Shixiong Ou Date: Thu, 6 Feb 2025 15:17:13 +0800 Subject: drm/bridge: convert to use devm_platform_ioremap_resource() convert to use devm_platform_ioremap_resource(). Signed-off-by: Shixiong Ou Reviewed-by: Maxime Ripard Acked-by: Manikandan Muralidharan Reviewed-and-tested-by: Dharma Balasubiramani Reviewed-by: Dharma Balasubiramani Tested-by: Dharma Balasubiramani Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250206071713.180471-1-oushixiong1025@163.com --- drivers/gpu/drm/bridge/microchip-lvds.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/microchip-lvds.c b/drivers/gpu/drm/bridge/microchip-lvds.c index b8313dad6072..53dd140a1b8d 100644 --- a/drivers/gpu/drm/bridge/microchip-lvds.c +++ b/drivers/gpu/drm/bridge/microchip-lvds.c @@ -162,8 +162,7 @@ static int mchp_lvds_probe(struct platform_device *pdev) lvds->dev = dev; - lvds->regs = devm_ioremap_resource(lvds->dev, - platform_get_resource(pdev, IORESOURCE_MEM, 0)); + lvds->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(lvds->regs)) return PTR_ERR(lvds->regs); -- cgit v1.2.3-59-g8ed1b From f74fd53ba34551b7626193fb70c17226f06e9bf1 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Wed, 5 Feb 2025 10:40:42 +0530 Subject: drm/xe/client: bo->client does not need bos_lock bos_lock is to protect list of bos used by client, it is not required to protect bo->client so bring it outside of bos_lock. Fixes: b27970f3e11c ("drm/xe: Add tracking support for bos per client") Signed-off-by: Tejas Upadhyay Reviewed-by: Himal Prasad Ghimiray Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20250205051042.1991192-1-tejas.upadhyay@intel.com Signed-off-by: Nirmoy Das --- drivers/gpu/drm/xe/xe_drm_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c index 63f30b6df70b..2d4874d2b922 100644 --- a/drivers/gpu/drm/xe/xe_drm_client.c +++ b/drivers/gpu/drm/xe/xe_drm_client.c @@ -135,8 +135,8 @@ void xe_drm_client_add_bo(struct xe_drm_client *client, XE_WARN_ON(bo->client); XE_WARN_ON(!list_empty(&bo->client_link)); - spin_lock(&client->bos_lock); bo->client = xe_drm_client_get(client); + spin_lock(&client->bos_lock); list_add_tail(&bo->client_link, &client->bos_list); spin_unlock(&client->bos_lock); } -- cgit v1.2.3-59-g8ed1b From 15d174fa85d936f3d0250b111e7d3b7f26a38b40 Mon Sep 17 00:00:00 2001 From: Langyan Ye Date: Sat, 8 Feb 2025 18:53:25 +0800 Subject: drm/panel: panel-himax-hx83102: support for kingdisplay-kd110n11-51ie MIPI-DSI panel The kingdisplay-kd110n11-51ie is a 10.95" TFT panel. The MIPI controller on this panel is the same as the other panels here, so add this panel to this driver. Signed-off-by: Langyan Ye Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250208105326.3850358-3-yelangyan@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-himax-hx83102.c | 115 ++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c index c3f4f5ee175d..9a818dea653f 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx83102.c +++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c @@ -494,6 +494,96 @@ static int ivo_t109nw41_init(struct hx83102 *ctx) return dsi_ctx.accum_err; }; +static int kingdisplay_kd110n11_51ie_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(50); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D9, 0xd1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb3, 0xb3, 0x31, 0xf1, + 0x33, 0xe0, 0x54, 0x36, 0x36, 0x3a, 0x3a, 0x32, 0x8b, + 0x11, 0xe5, 0x98); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x8b, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x2c, + 0x80, 0x3c, 0x9f, 0x22, 0x20, 0x00, 0x00, 0x98, 0x51); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x40, 0x84, 0x64, 0x84, 0x01, 0x9d, 0x01, 0x02, 0x01, 0x00, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4, 0x80, 0x9c, 0x36, 0x00, + 0x0d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x32, 0x32, 0x22, 0x11, 0x22, 0xa0, + 0x31, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, + 0x0f, 0x36); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, + 0x04, 0x2c, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x40, 0x04, + 0x08, 0x04, 0x08, 0x37, 0x07, 0x44, 0x37, 0x2b, 0x2b, 0x03, + 0x03, 0x32, 0x10, 0x22, 0x00, 0x25, 0x32, 0x10, 0x29, 0x00, + 0x29, 0x32, 0x10, 0x08, 0x00, 0x08, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, + 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x18, 0x18, 0x25, 0x24, 0x25, 0x24, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1e, 0x1e, 0x1e, 0x1e, 0x20, 0x20, 0x20, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xe0, 0x10, 0x10, 0x0d, 0x1e, 0x9d, + 0x02, 0x52, 0x9d, 0x14, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x64); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x05, 0x15, 0x55, 0x45, + 0x55, 0x50, 0x05, 0x15, 0x55, 0x45, 0x55, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x24, 0x01, 0x7e, 0x0f, + 0x7c, 0x10, 0xa0, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0, + 0x0f, 0x3f, 0xff, 0xcf, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, + 0x20, 0x9d, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x66, 0x81); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, + 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0, 0x0f, 0x2a, 0xaa, 0x8a, + 0xaa, 0xf0, 0x0f, 0x2a, 0xaa, 0x8a, 0xaa, 0xf0, 0x0a, 0x2a, + 0xaa, 0x8a, 0xaa, 0xa0, 0x0a, 0x2a, 0xaa, 0x8a, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + return dsi_ctx.accum_err; +} + static const struct drm_display_mode starry_mode = { .clock = 162680, .hdisplay = 1200, @@ -582,6 +672,28 @@ static const struct hx83102_panel_desc ivo_t109nw41_desc = { .init = ivo_t109nw41_init, }; +static const struct drm_display_mode kingdisplay_kd110n11_51ie_default_mode = { + .clock = 182750, + .hdisplay = 1200, + .hsync_start = 1200 + 124, + .hsync_end = 1200 + 124 + 80, + .htotal = 1200 + 124 + 80 + 80, + .vdisplay = 1920, + .vsync_start = 1920 + 88, + .vsync_end = 1920 + 88 + 8, + .vtotal = 1920 + 88 + 8 + 38, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc kingdisplay_kd110n11_51ie_desc = { + .modes = &kingdisplay_kd110n11_51ie_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = kingdisplay_kd110n11_51ie_init, +}; + static int hx83102_enable(struct drm_panel *panel) { msleep(130); @@ -809,6 +921,9 @@ static const struct of_device_id hx83102_of_match[] = { { .compatible = "ivo,t109nw41", .data = &ivo_t109nw41_desc }, + { .compatible = "kingdisplay,kd110n11-51ie", + .data = &kingdisplay_kd110n11_51ie_desc + }, { .compatible = "starry,himax83102-j02", .data = &starry_desc }, -- cgit v1.2.3-59-g8ed1b From 1b80b2101d7b433718a21a9e7d413e066bf8aec6 Mon Sep 17 00:00:00 2001 From: Langyan Ye Date: Sat, 8 Feb 2025 18:53:26 +0800 Subject: drm/panel: panel-himax-hx83102: support for starry-2082109qfh040022-50e MIPI-DSI panel The starry-2082109qfh040022-50e is a 10.95" TFT panel. The MIPI controller on this panel is the same as the other panels here, so add this panel to this driver. Signed-off-by: Langyan Ye Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250208105326.3850358-4-yelangyan@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-himax-hx83102.c | 142 ++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c index 9a818dea653f..66abfc44e424 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx83102.c +++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c @@ -24,6 +24,8 @@ #define HX83102_SETPOWER 0xb1 #define HX83102_SETDISP 0xb2 #define HX83102_SETCYC 0xb4 +#define HX83102_UNKNOWN_B6 0xb6 +#define HX83102_UNKNOWN_B8 0xb8 #define HX83102_SETEXTC 0xb9 #define HX83102_SETMIPI 0xba #define HX83102_SETVDC 0xbc @@ -584,6 +586,121 @@ static int kingdisplay_kd110n11_51ie_init(struct hx83102 *ctx) return dsi_ctx.accum_err; } +static int starry_2082109qfh040022_50e_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(50); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D9, 0xd1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb5, 0xb5, 0x31, 0xf1, 0x33, + 0xc3, 0x57, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, 0x65, + 0x00, 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x3c, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x22, + 0x70, 0x3c, 0xa1, 0x22, 0x00, 0x00, 0x00, 0x88, 0xf4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x14, 0x16, 0x14, 0x50, 0x14, 0x50, + 0x0d, 0x6a, 0x0d, 0x6a, 0x01, 0x9e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_B6, 0x34, 0x34, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_B8, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x38, 0x38, 0x22, 0x11, 0x33, 0xa0, + 0x61, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x30, 0xd4, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, + 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, + 0x2c, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3b, 0x03, 0x73, 0x3b, 0x21, 0x21, 0x03, + 0x03, 0x98, 0x10, 0x1d, 0x00, 0x1d, 0x32, 0x17, 0xa1, 0x07, + 0xa1, 0x43, 0x17, 0xa6, 0x07, 0xa6, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x40, 0x40, 0x18, 0x18, 0x18, 0x18, 0x2a, 0x2b, 0x1f, 0x1f, + 0x1e, 0x1e, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x20, 0x21, 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x02, 0xaa, 0xea, 0xaa, 0xaa, 0x00, + 0x02, 0xaa, 0xea, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x2a, 0x32, 0x9f, + 0x01, 0x5a, 0x91, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x05, 0x02, 0x02, 0x10, 0x33, 0x02, 0x04, 0x18, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x00, 0x80, 0x80, 0x0c, + 0xa1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2d, 0x01, 0x7f, 0x0f, + 0x7c, 0x10, 0xa0, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x02, 0x00, 0x00, 0x10, 0x58); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x0a, 0x0a, 0x05, 0x03, 0x0a, + 0x0a, 0x01, 0x03, 0x01, 0x01, 0x05, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x03, 0x1f, 0xe0, 0x11, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xab, 0xff, 0xff, 0xff, 0xff, 0xa0, + 0xab, 0xff, 0xff, 0xff, 0xff, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x81, 0x02, 0x40, 0x00, + 0x20, 0x9e, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xab, 0xea, 0xaa, 0xaa, 0xa0, + 0xaa, 0xab, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xbf, 0xff, 0xff, + 0xfe, 0xa0, 0xaa, 0xbf, 0xff, 0xff, 0xfe, 0xa0, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + mipi_dsi_msleep(&dsi_ctx, 110); + + return dsi_ctx.accum_err; +} + static const struct drm_display_mode starry_mode = { .clock = 162680, .hdisplay = 1200, @@ -694,6 +811,28 @@ static const struct hx83102_panel_desc kingdisplay_kd110n11_51ie_desc = { .init = kingdisplay_kd110n11_51ie_init, }; +static const struct drm_display_mode starry_2082109qfh040022_50e_default_mode = { + .clock = 192050, + .hdisplay = 1200, + .hsync_start = 1200 + 160, + .hsync_end = 1200 + 160 + 66, + .htotal = 1200 + 160 + 66 + 120, + .vdisplay = 1920, + .vsync_start = 1920 + 115, + .vsync_end = 1920 + 115 + 8, + .vtotal = 1920 + 115 + 8 + 28, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc starry_2082109qfh040022_50e_desc = { + .modes = &starry_2082109qfh040022_50e_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = starry_2082109qfh040022_50e_init, +}; + static int hx83102_enable(struct drm_panel *panel) { msleep(130); @@ -924,6 +1063,9 @@ static const struct of_device_id hx83102_of_match[] = { { .compatible = "kingdisplay,kd110n11-51ie", .data = &kingdisplay_kd110n11_51ie_desc }, + { .compatible = "starry,2082109qfh040022-50e", + .data = &starry_2082109qfh040022_50e_desc + }, { .compatible = "starry,himax83102-j02", .data = &starry_desc }, -- cgit v1.2.3-59-g8ed1b From f4e71f66036872e67a5eeb5800828541da5d12c9 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 6 Feb 2025 18:02:34 +0100 Subject: drm/bridge: nxp-ptn3460: remove unused drm_panel.h include The file uses the panel_bridge APIs from drm_bridge.h, but no drm_panel APIs from drm_panel.h. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250206-drm-cleanups-v1-2-93df60faa756@bootlin.com --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 44e36ae66db4..27261b2ac9c8 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3-59-g8ed1b From 202f3f60d1743cacb4924566daac846d33be5378 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 6 Feb 2025 18:02:35 +0100 Subject: drm/bridge: parade-ps8622: remove unused drm_panel.h include The file uses the panel_bridge APIs from drm_bridge.h, but no drm_panel APIs from drm_panel.h. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250206-drm-cleanups-v1-3-93df60faa756@bootlin.com --- drivers/gpu/drm/bridge/parade-ps8622.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index ae3ab9262ef1..13ada42a5514 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3-59-g8ed1b From 10fab0675483617867e1f4f59f1b1fe9bd4d719d Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 6 Feb 2025 18:02:36 +0100 Subject: drm/bridge: parade-ps8640: remove unused drm_panel.h include The file uses the panel_bridge APIs from drm_bridge.h, but no drm_panel APIs from drm_panel.h. Signed-off-by: Luca Ceresoli Reviewed-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250206-drm-cleanups-v1-4-93df60faa756@bootlin.com --- drivers/gpu/drm/bridge/parade-ps8640.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 14d4dcf239da..b0e38177c1ec 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #define PAGE0_AUXCH_CFG3 0x76 -- cgit v1.2.3-59-g8ed1b From 38e092786e54ae102eafe07c938aa289895639f1 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 6 Feb 2025 18:02:37 +0100 Subject: drm/bridge: tc358762: remove unused drm_panel.h include, add drm_bridge.h The file uses the panel_bridge APIs from drm_bridge.h, which is included only indirectly, and uses no drm_panel APIs from drm_panel.h. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250206-drm-cleanups-v1-5-93df60faa756@bootlin.com --- drivers/gpu/drm/bridge/tc358762.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index 46198af9eebb..f92aff3d515a 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -20,10 +20,10 @@ #include