:p
atchew
Login
struct drm_simple_display_pipe was meant to simplify simple DRM drivers, but instead adds an extra wrapper around normal DRM atomic helper setup. As noted in Documentation/gpu/todo.rst, remaining users should be converted to regular atomic helpers and stop depending on the simple-KMS interfaces. This series converts the following drivers: - arcpgu - aspeed - imx lcdc - mcde - pl111 - gm12u320 - repaper - tve200 - xen frontend Each patch replaces drm_simple_display_pipe_init() with explicit primary plane, CRTC and encoder setup, and moves the old simple-pipe callbacks into regular plane and CRTC helper callbacks named according to local driver conventions. The conversions preserve helper behavior that used to be implicit in drm_simple_kms_helper.c, including plane-state validation, CRTC primary-plane checks, affected-plane propagation, framebuffer prepare handling, and existing event/vblank flow where applicable. Result is less helper indirection and more explicit driver-side atomic wiring, with no remaining simple-KMS dependency in these drivers. These changes are build-tested only. No hardware testing has been performed on the affected devices. This series is based on drm-next-2026-06-27. Thanks, Ze Huang Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- Ze Huang (9): drm/arcpgu: replace struct drm_simple_display_pipe with regular atomic helpers drm/aspeed: replace struct drm_simple_display_pipe with regular atomic helpers drm/imx: replace struct drm_simple_display_pipe with regular atomic helpers drm/mcde: replace struct drm_simple_display_pipe with regular atomic helpers drm/pl111: replace struct drm_simple_display_pipe with regular atomic helpers drm/gm12u320: replace struct drm_simple_display_pipe with regular atomic helpers drm/repaper: replace struct drm_simple_display_pipe with regular atomic helpers drm/tve200: replace struct drm_simple_display_pipe with regular atomic helpers drm/xen: replace struct drm_simple_display_pipe with regular atomic helpers drivers/gpu/drm/aspeed/aspeed_gfx.h | 5 +- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 156 ++++++++++++++++------ drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 3 +- drivers/gpu/drm/imx/lcdc/imx-lcdc.c | 178 ++++++++++++++++++------- drivers/gpu/drm/mcde/mcde_display.c | 162 ++++++++++++++++------ drivers/gpu/drm/mcde/mcde_drm.h | 6 +- drivers/gpu/drm/mcde/mcde_drv.c | 3 +- drivers/gpu/drm/pl111/pl111_display.c | 174 ++++++++++++++++++------ drivers/gpu/drm/pl111/pl111_drm.h | 5 +- drivers/gpu/drm/pl111/pl111_drv.c | 3 +- drivers/gpu/drm/tiny/arcpgu.c | 165 ++++++++++++++++++----- drivers/gpu/drm/tiny/gm12u320.c | 128 ++++++++++++++---- drivers/gpu/drm/tiny/repaper.c | 130 ++++++++++++++---- drivers/gpu/drm/tve200/tve200_display.c | 221 +++++++++++++++++++++---------- drivers/gpu/drm/tve200/tve200_drm.h | 6 +- drivers/gpu/drm/tve200/tve200_drv.c | 17 ++- drivers/gpu/drm/xen/xen_drm_front.h | 6 +- drivers/gpu/drm/xen/xen_drm_front_kms.c | 177 +++++++++++++++++++------ 18 files changed, 1164 insertions(+), 381 deletions(-) --- base-commit: 3696d07837d1df13a5603d77f667685e7dfb3c53 change-id: 20260704-drm-simple-kms-removal-01a031c6a129 Best regards, -- Ze Huang <ze.huang@oss.qualcomm.com>
Instantiate plane, CRTC and encoder directly and wire them up with standard atomic helpers. This removes arcpgu's dependency on deprecated simple-KMS display pipe interface. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tiny/arcpgu.c | 165 +++++++++++++++++++++++++++++++++--------- 1 file changed, 131 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tiny/arcpgu.c +++ b/drivers/gpu/drm/tiny/arcpgu.c @@ -XXX,XX +XXX,XX @@ #include <drm/drm_fbdev_dma.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> +#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/of_reserved_mem.h> @@ -XXX,XX +XXX,XX @@ struct arcpgu_drm_private { struct drm_device drm; void __iomem *regs; struct clk *clk; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector sim_conn; }; #define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm) -#define pipe_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe) - static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, unsigned int reg, u32 value) { @@ -XXX,XX +XXX,XX @@ static const u32 arc_pgu_supported_formats[] = { static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) { - const struct drm_framebuffer *fb = arcpgu->pipe.plane.state->fb; + const struct drm_framebuffer *fb = arcpgu->plane.state->fb; uint32_t pixel_format = fb->format->format; u32 format = DRM_FORMAT_INVALID; int i; @@ -XXX,XX +XXX,XX @@ static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, reg_ctrl); } -static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +static enum drm_mode_status arcpgu_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(crtc->dev); long rate, clk_rate = mode->clock * 1000; long diff = clk_rate / 200; /* +-0.5% allowed by HDMI spec */ @@ -XXX,XX +XXX,XX @@ static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *p static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) { - struct drm_display_mode *m = &arcpgu->pipe.crtc.state->adjusted_mode; + struct drm_display_mode *m = &arcpgu->crtc.state->adjusted_mode; u32 val; arc_pgu_write(arcpgu, ARCPGU_REG_FMT, @@ -XXX,XX +XXX,XX @@ static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); } -static void arc_pgu_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void arcpgu_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(crtc->dev); arc_pgu_mode_set(arcpgu); @@ -XXX,XX +XXX,XX @@ static void arc_pgu_enable(struct drm_simple_display_pipe *pipe, ARCPGU_CTRL_ENABLE_MASK); } -static void arc_pgu_disable(struct drm_simple_display_pipe *pipe) +static void arcpgu_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(crtc->dev); clk_disable_unprepare(arcpgu->clk); arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, @@ -XXX,XX +XXX,XX @@ static void arc_pgu_disable(struct drm_simple_display_pipe *pipe) ~ARCPGU_CTRL_ENABLE_MASK); } -static void arc_pgu_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *state) +static void arcpgu_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *state) { struct arcpgu_drm_private *arcpgu; struct drm_gem_dma_object *gem; - if (!pipe->plane.state->fb) + if (!plane->state->fb) return; - arcpgu = pipe_to_arcpgu_priv(pipe); - gem = drm_fb_dma_get_gem_obj(pipe->plane.state->fb, 0); + arcpgu = dev_to_arcpgu(plane->dev); + gem = drm_fb_dma_get_gem_obj(plane->state->fb, 0); arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->dma_addr); } -static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = { - .update = arc_pgu_update, - .mode_valid = arc_pgu_mode_valid, - .enable = arc_pgu_enable, - .disable = arc_pgu_disable, -}; - static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { - .fb_create = drm_gem_fb_create, + .fb_create = drm_gem_fb_create, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, }; DEFINE_DRM_GEM_DMA_FOPS(arcpgu_drm_ops); +static int arcpgu_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + return ret; +} + +static const struct drm_plane_helper_funcs arcpgu_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = arcpgu_plane_helper_atomic_check, + .atomic_update = arcpgu_plane_helper_atomic_update, +}; + +static bool arcpgu_plane_format_mod_supported(struct drm_plane *plane, + u32 format, + u64 modifier) +{ + return modifier == DRM_FORMAT_MOD_LINEAR; +} + +static const struct drm_plane_funcs arcpgu_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + .format_mod_supported = arcpgu_plane_format_mod_supported, +}; + +static int arcpgu_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_crtc_helper_funcs arcpgu_crtc_helper_funcs = { + .mode_valid = arcpgu_crtc_helper_mode_valid, + .atomic_check = arcpgu_crtc_helper_atomic_check, + .atomic_enable = arcpgu_crtc_helper_atomic_enable, + .atomic_disable = arcpgu_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs arcpgu_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs arcpgu_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + static int arcpgu_load(struct arcpgu_drm_private *arcpgu) { struct platform_device *pdev = to_platform_device(arcpgu->drm.dev); @@ -XXX,XX +XXX,XX @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) struct device_node *endpoint_node = NULL; struct drm_connector *connector = NULL; struct drm_device *drm = &arcpgu->drm; + struct drm_plane *plane; + struct drm_encoder *encoder; + struct drm_crtc *crtc; int ret; arcpgu->clk = devm_clk_get(drm->dev, "pxlclk"); @@ -XXX,XX +XXX,XX @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) return ret; } - ret = drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs, - arc_pgu_supported_formats, - ARRAY_SIZE(arc_pgu_supported_formats), - NULL, connector); + plane = &arcpgu->plane; + ret = drm_universal_plane_init(drm, plane, 0, + &arcpgu_plane_funcs, + arc_pgu_supported_formats, + ARRAY_SIZE(arc_pgu_supported_formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) return ret; + drm_plane_helper_add(plane, &arcpgu_plane_helper_funcs); + + crtc = &arcpgu->crtc; + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, + &arcpgu_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(crtc, &arcpgu_crtc_helper_funcs); + + encoder = &arcpgu->encoder; + ret = drm_encoder_init(drm, encoder, &arcpgu_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + encoder->possible_crtcs = drm_crtc_mask(crtc); + + if (connector) { + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) + return ret; + } if (encoder_node) { /* Locate drm bridge from the hdmi encoder DT node */ @@ -XXX,XX +XXX,XX @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (!bridge) return -EPROBE_DEFER; - ret = drm_simple_display_pipe_attach_bridge(&arcpgu->pipe, bridge); + ret = drm_bridge_attach(encoder, bridge, NULL, 0); if (ret) return ret; } @@ -XXX,XX +XXX,XX @@ static int arcpgu_show_pxlclock(struct seq_file *m, void *arg) struct drm_device *drm = node->minor->dev; struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); unsigned long clkrate = clk_get_rate(arcpgu->clk); - unsigned long mode_clock = arcpgu->pipe.crtc.mode.crtc_clock * 1000; + unsigned long mode_clock = arcpgu->crtc.mode.crtc_clock * 1000; seq_printf(m, "hw : %lu\n", clkrate); seq_printf(m, "mode: %lu\n", mode_clock); -- 2.55.0
Replace simple display pipe with explicit plane, CRTC and encoder objects. Move callbacks to plane and CRTC helpers, with vblank handling through drm_crtc_funcs. This removes intermediate simple-pipe layer and uses standard atomic helper wiring. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/aspeed/aspeed_gfx.h | 5 +- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 156 +++++++++++++++++++++++-------- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 3 +- 3 files changed, 123 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx.h b/drivers/gpu/drm/aspeed/aspeed_gfx.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx.h +++ b/drivers/gpu/drm/aspeed/aspeed_gfx.h @@ -XXX,XX +XXX,XX @@ /* Copyright 2018 IBM Corporation */ #include <drm/drm_device.h> -#include <drm/drm_simple_kms_helper.h> struct aspeed_gfx { struct drm_device drm; @@ -XXX,XX +XXX,XX @@ struct aspeed_gfx { u32 throd_val; u32 scan_line_max; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector connector; }; #define to_aspeed_gfx(x) container_of(x, struct aspeed_gfx, drm) diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -XXX,XX +XXX,XX @@ #include <linux/reset.h> #include <linux/regmap.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_device.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_panel.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> #include "aspeed_gfx.h" -static struct aspeed_gfx * -drm_pipe_to_aspeed_gfx(struct drm_simple_display_pipe *pipe) -{ - return container_of(pipe, struct aspeed_gfx, pipe); -} - static int aspeed_gfx_set_pixel_fmt(struct aspeed_gfx *priv, u32 *bpp) { - struct drm_crtc *crtc = &priv->pipe.crtc; + struct drm_crtc *crtc = &priv->crtc; struct drm_device *drm = crtc->dev; const u32 format = crtc->primary->state->fb->format->format; u32 ctrl1; @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_disable_controller(struct aspeed_gfx *priv) static void aspeed_gfx_crtc_mode_set_nofb(struct aspeed_gfx *priv) { - struct drm_display_mode *m = &priv->pipe.crtc.state->adjusted_mode; + struct drm_display_mode *m = &priv->crtc.state->adjusted_mode; u32 ctrl1, d_offset, t_count, bpp; int err; @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_crtc_mode_set_nofb(struct aspeed_gfx *priv) writel(priv->throd_val, priv->base + CRT_THROD); } -static void aspeed_gfx_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void aspeed_gfx_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct aspeed_gfx *priv = container_of(crtc, struct aspeed_gfx, crtc); aspeed_gfx_crtc_mode_set_nofb(priv); aspeed_gfx_enable_controller(priv); drm_crtc_vblank_on(crtc); } -static void aspeed_gfx_pipe_disable(struct drm_simple_display_pipe *pipe) +static void aspeed_gfx_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct aspeed_gfx *priv = container_of(crtc, struct aspeed_gfx, crtc); drm_crtc_vblank_off(crtc); aspeed_gfx_disable_controller(priv); } -static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state) +static void aspeed_gfx_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *state) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); - struct drm_crtc *crtc = &pipe->crtc; - struct drm_framebuffer *fb = pipe->plane.state->fb; + struct aspeed_gfx *priv = container_of(plane, struct aspeed_gfx, plane); + struct drm_crtc *crtc = &priv->crtc; + struct drm_framebuffer *fb = plane->state->fb; struct drm_pending_vblank_event *event; struct drm_gem_dma_object *gem; @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, writel(gem->dma_addr, priv->base + CRT_ADDR); } -static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe) +static int aspeed_gfx_crtc_enable_vblank(struct drm_crtc *crtc) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); + struct aspeed_gfx *priv = container_of(crtc, struct aspeed_gfx, crtc); u32 reg = readl(priv->base + CRT_CTRL1); /* Clear pending VBLANK IRQ */ @@ -XXX,XX +XXX,XX @@ static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void aspeed_gfx_disable_vblank(struct drm_simple_display_pipe *pipe) +static void aspeed_gfx_crtc_disable_vblank(struct drm_crtc *crtc) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); + struct aspeed_gfx *priv = container_of(crtc, struct aspeed_gfx, crtc); u32 reg = readl(priv->base + CRT_CTRL1); reg &= ~CRT_CTRL_VERTICAL_INTR_EN; @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_disable_vblank(struct drm_simple_display_pipe *pipe) writel(reg | CRT_CTRL_VERTICAL_INTR_STS, priv->base + CRT_CTRL1); } -static const struct drm_simple_display_pipe_funcs aspeed_gfx_funcs = { - .enable = aspeed_gfx_pipe_enable, - .disable = aspeed_gfx_pipe_disable, - .update = aspeed_gfx_pipe_update, - .enable_vblank = aspeed_gfx_enable_vblank, - .disable_vblank = aspeed_gfx_disable_vblank, +static int aspeed_gfx_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + return ret; +} + +static const struct drm_plane_helper_funcs aspeed_gfx_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = aspeed_gfx_plane_helper_atomic_check, + .atomic_update = aspeed_gfx_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs aspeed_gfx_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static int aspeed_gfx_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_crtc_helper_funcs aspeed_gfx_crtc_helper_funcs = { + .atomic_check = aspeed_gfx_crtc_helper_atomic_check, + .atomic_enable = aspeed_gfx_crtc_helper_atomic_enable, + .atomic_disable = aspeed_gfx_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs aspeed_gfx_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = aspeed_gfx_crtc_enable_vblank, + .disable_vblank = aspeed_gfx_crtc_disable_vblank, +}; + +static const struct drm_encoder_funcs aspeed_gfx_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static const uint32_t aspeed_gfx_formats[] = { @@ -XXX,XX +XXX,XX @@ static const uint32_t aspeed_gfx_formats[] = { int aspeed_gfx_create_pipe(struct drm_device *drm) { struct aspeed_gfx *priv = to_aspeed_gfx(drm); + struct drm_plane *plane = &priv->plane; + struct drm_crtc *crtc = &priv->crtc; + struct drm_encoder *encoder = &priv->encoder; + int ret; + + ret = drm_universal_plane_init(drm, plane, 0, + &aspeed_gfx_plane_funcs, + aspeed_gfx_formats, + ARRAY_SIZE(aspeed_gfx_formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(plane, &aspeed_gfx_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, + &aspeed_gfx_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(crtc, &aspeed_gfx_crtc_helper_funcs); + + ret = drm_encoder_init(drm, encoder, &aspeed_gfx_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + encoder->possible_crtcs = drm_crtc_mask(crtc); + + ret = drm_connector_attach_encoder(&priv->connector, encoder); + if (ret) + return ret; - return drm_simple_display_pipe_init(drm, &priv->pipe, &aspeed_gfx_funcs, - aspeed_gfx_formats, - ARRAY_SIZE(aspeed_gfx_formats), - NULL, - &priv->connector); + return 0; } diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -XXX,XX +XXX,XX @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> #include <drm/drm_drv.h> @@ -XXX,XX +XXX,XX @@ static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data) reg = readl(priv->base + CRT_CTRL1); if (reg & CRT_CTRL_VERTICAL_INTR_STS) { - drm_crtc_handle_vblank(&priv->pipe.crtc); + drm_crtc_handle_vblank(&priv->crtc); writel(reg, priv->base + priv->int_clr_reg); return IRQ_HANDLED; } -- 2.55.0
Convert i.MX LCDC to explicit primary plane, CRTC and encoder objects. Keep no-scaling plane check and GEM framebuffer prepare callback from simple-KMS path. Only touch hardware state when framebuffer exists, since atomic plane updates can run on disabling transitions. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/imx/lcdc/imx-lcdc.c | 178 ++++++++++++++++++++++++++---------- 1 file changed, 130 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c +++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c @@ -XXX,XX +XXX,XX @@ #include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> +#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> #include <linux/bitfield.h> #include <linux/clk.h> @@ -XXX,XX +XXX,XX @@ struct imx_lcdc { struct drm_device drm; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector *connector; void __iomem *base; @@ -XXX,XX +XXX,XX @@ static unsigned int imx_lcdc_get_format(unsigned int drm_format) } } -static void imx_lcdc_update_hw_registers(struct drm_simple_display_pipe *pipe, +static void imx_lcdc_update_hw_registers(struct drm_crtc *crtc, struct drm_plane_state *old_state, bool mode_set) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_plane_state *new_state = pipe->plane.state; + struct drm_plane_state *new_state = crtc->primary->state; struct drm_framebuffer *fb = new_state->fb; - struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(pipe->crtc.dev); + struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(crtc->dev); u32 lpcr, lvcr, lhcr; u32 framesize; dma_addr_t addr; @@ -XXX,XX +XXX,XX @@ static void imx_lcdc_update_hw_registers(struct drm_simple_display_pipe *pipe, clk_prepare_enable(lcdc->clk_per); } -static void imx_lcdc_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void imx_lcdc_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { int ret; int clk_div; int bpp; - struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(pipe->crtc.dev); - struct drm_display_mode *mode = &pipe->crtc.mode; + struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(crtc->dev); + struct drm_display_mode *mode = &crtc->mode; struct drm_display_info *disp_info = &lcdc->connector->display_info; + struct drm_plane_state *plane_state = crtc->primary->state; const int hsync_pol = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : 1; const int vsync_pol = (mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : 1; const int data_enable_pol = @@ -XXX,XX +XXX,XX @@ static void imx_lcdc_pipe_enable(struct drm_simple_display_pipe *pipe, ret = clk_prepare_enable(lcdc->clk_ipg); if (ret) { - dev_err(pipe->crtc.dev->dev, "Cannot enable ipg clock: %pe\n", ERR_PTR(ret)); + dev_err(crtc->dev->dev, "Cannot enable ipg clock: %pe\n", ERR_PTR(ret)); return; } ret = clk_prepare_enable(lcdc->clk_ahb); if (ret) { - dev_err(pipe->crtc.dev->dev, "Cannot enable ahb clock: %pe\n", ERR_PTR(ret)); + dev_err(crtc->dev->dev, "Cannot enable ahb clock: %pe\n", ERR_PTR(ret)); clk_disable_unprepare(lcdc->clk_ipg); return; } - imx_lcdc_update_hw_registers(pipe, NULL, true); + imx_lcdc_update_hw_registers(crtc, NULL, true); /* Enable VBLANK Interrupt */ writel(INTR_EOF, lcdc->base + IMX21LCDC_LIER); } -static void imx_lcdc_pipe_disable(struct drm_simple_display_pipe *pipe) +static void imx_lcdc_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(pipe->crtc.dev); - struct drm_crtc *crtc = &lcdc->pipe.crtc; + struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(crtc->dev); struct drm_pending_vblank_event *event; clk_disable_unprepare(lcdc->clk_ahb); clk_disable_unprepare(lcdc->clk_ipg); - if (pipe->crtc.enabled) + if (crtc->enabled) clk_disable_unprepare(lcdc->clk_per); spin_lock_irq(&lcdc->drm.event_lock); @@ -XXX,XX +XXX,XX @@ static void imx_lcdc_pipe_disable(struct drm_simple_display_pipe *pipe) writel(0, lcdc->base + IMX21LCDC_LIER); } -static int imx_lcdc_pipe_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state) +static int imx_lcdc_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); const struct drm_display_mode *mode = &crtc_state->mode; - const struct drm_display_mode *old_mode = &pipe->crtc.state->mode; + const struct drm_display_mode *old_mode = &crtc->state->mode; + int ret; if (mode->hdisplay < LCDC_MIN_XRES || mode->hdisplay > LCDC_MAX_XRES || mode->vdisplay < LCDC_MIN_YRES || mode->vdisplay > LCDC_MAX_YRES || mode->hdisplay % 0x10) { /* must be multiple of 16 */ - drm_err(pipe->crtc.dev, "unsupported display mode (%u x %u)\n", + drm_err(crtc->dev, "unsupported display mode (%u x %u)\n", mode->hdisplay, mode->vdisplay); return -EINVAL; } @@ -XXX,XX +XXX,XX @@ static int imx_lcdc_pipe_check(struct drm_simple_display_pipe *pipe, old_mode->hdisplay != mode->hdisplay || old_mode->vdisplay != mode->vdisplay; - return 0; + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); } -static void imx_lcdc_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) +static void imx_lcdc_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_pending_vblank_event *event = crtc->state->event; - struct drm_plane_state *new_state = pipe->plane.state; + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane); + struct drm_plane_state *new_state = plane->state; + struct drm_crtc *crtc = new_state->crtc ?: old_state->crtc; + struct drm_pending_vblank_event *event; struct drm_framebuffer *fb = new_state->fb; struct drm_framebuffer *old_fb = old_state->fb; struct drm_crtc *old_crtc = old_state->crtc; bool mode_changed = false; - if (old_fb && old_fb->format != fb->format) - mode_changed = true; - else if (old_crtc != crtc) - mode_changed = true; + if (!crtc) + return; - imx_lcdc_update_hw_registers(pipe, old_state, mode_changed); + if (fb) { + if (old_fb && old_fb->format != fb->format) + mode_changed = true; + else if (old_crtc != crtc) + mode_changed = true; + imx_lcdc_update_hw_registers(crtc, old_state, mode_changed); + } + + event = crtc->state->event; if (event) { crtc->state->event = NULL; @@ -XXX,XX +XXX,XX @@ static void imx_lcdc_pipe_update(struct drm_simple_display_pipe *pipe, } } -static const struct drm_simple_display_pipe_funcs imx_lcdc_pipe_funcs = { - .enable = imx_lcdc_pipe_enable, - .disable = imx_lcdc_pipe_disable, - .check = imx_lcdc_pipe_check, - .update = imx_lcdc_pipe_update, +static int imx_lcdc_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + return ret; +} + +static const struct drm_plane_helper_funcs imx_lcdc_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = imx_lcdc_plane_helper_atomic_check, + .atomic_update = imx_lcdc_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs imx_lcdc_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const struct drm_crtc_helper_funcs imx_lcdc_crtc_helper_funcs = { + .atomic_check = imx_lcdc_crtc_helper_atomic_check, + .atomic_enable = imx_lcdc_crtc_helper_atomic_enable, + .atomic_disable = imx_lcdc_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs imx_lcdc_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs imx_lcdc_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static const struct drm_mode_config_funcs imx_lcdc_mode_config_funcs = { @@ -XXX,XX +XXX,XX @@ MODULE_DEVICE_TABLE(of, imx_lcdc_of_dev_id); static irqreturn_t imx_lcdc_irq_handler(int irq, void *arg) { struct imx_lcdc *lcdc = arg; - struct drm_crtc *crtc = &lcdc->pipe.crtc; + struct drm_crtc *crtc = &lcdc->crtc; unsigned int status; status = readl(lcdc->base + IMX21LCDC_LISR); @@ -XXX,XX +XXX,XX @@ static int imx_lcdc_probe(struct platform_device *pdev) struct imx_lcdc *lcdc; struct drm_device *drm; struct drm_bridge *bridge; + struct drm_plane *plane; + struct drm_crtc *crtc; + struct drm_encoder *encoder; int irq; int ret; struct device *dev = &pdev->dev; @@ -XXX,XX +XXX,XX @@ static int imx_lcdc_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "Cannot initialize mode configuration structure\n"); - /* CRTC, Plane, Encoder */ - ret = drm_simple_display_pipe_init(drm, &lcdc->pipe, - &imx_lcdc_pipe_funcs, - imx_lcdc_formats, - ARRAY_SIZE(imx_lcdc_formats), NULL, NULL); + plane = &lcdc->plane; + ret = drm_universal_plane_init(drm, plane, 0, + &imx_lcdc_plane_funcs, + imx_lcdc_formats, + ARRAY_SIZE(imx_lcdc_formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret < 0) + return dev_err_probe(drm->dev, ret, "Cannot initialize primary plane\n"); + drm_plane_helper_add(plane, &imx_lcdc_plane_helper_funcs); + + crtc = &lcdc->crtc; + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, + &imx_lcdc_crtc_funcs, NULL); + if (ret < 0) + return dev_err_probe(drm->dev, ret, "Cannot initialize CRTC\n"); + drm_crtc_helper_add(crtc, &imx_lcdc_crtc_helper_funcs); + + encoder = &lcdc->encoder; + ret = drm_encoder_init(drm, encoder, &imx_lcdc_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); if (ret < 0) - return dev_err_probe(drm->dev, ret, "Cannot setup simple display pipe\n"); + return dev_err_probe(drm->dev, ret, "Cannot initialize encoder\n"); + encoder->possible_crtcs = drm_crtc_mask(crtc); ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) return dev_err_probe(drm->dev, ret, "Failed to initialize vblank\n"); - ret = drm_bridge_attach(&lcdc->pipe.encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); + ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) return dev_err_probe(drm->dev, ret, "Cannot attach bridge\n"); - lcdc->connector = drm_bridge_connector_init(drm, &lcdc->pipe.encoder); + lcdc->connector = drm_bridge_connector_init(drm, encoder); if (IS_ERR(lcdc->connector)) return dev_err_probe(drm->dev, PTR_ERR(lcdc->connector), "Cannot init bridge connector\n"); -- 2.55.0
Convert MCDE to explicit plane, CRTC and encoder objects. Keep FIFO, event and framebuffer update sequencing intact, and install GEM framebuffer prepare callback explicitly. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/mcde/mcde_display.c | 162 +++++++++++++++++++++++++++--------- drivers/gpu/drm/mcde/mcde_drm.h | 6 +- drivers/gpu/drm/mcde/mcde_drv.c | 3 +- 3 files changed, 129 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -XXX,XX +XXX,XX @@ #include <linux/regulator/consumer.h> #include <linux/media-bus-format.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_device.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_gem_dma_helper.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_print.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_vblank.h> #include <video/mipi_display.h> @@ -XXX,XX +XXX,XX @@ void mcde_display_irq(struct mcde *mcde) writel(mispp, mcde->regs + MCDE_RISPP); if (vblank) - drm_crtc_handle_vblank(&mcde->pipe.crtc); + drm_crtc_handle_vblank(&mcde->crtc); if (misovl) dev_info(mcde->dev, "some stray overlay IRQ %08x\n", misovl); @@ -XXX,XX +XXX,XX @@ void mcde_display_disable_irqs(struct mcde *mcde) writel(0xFFFFFFFF, mcde->regs + MCDE_RISCHNL); } -static int mcde_display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *pstate, - struct drm_crtc_state *cstate) +static int mcde_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) { - const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *old_fb = pipe->plane.state->fb; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = pstate->crtc; + struct drm_crtc_state *cstate; + const struct drm_display_mode *mode; + struct drm_framebuffer *old_fb = plane->state->fb; struct drm_framebuffer *fb = pstate->fb; + int ret; + + if (!crtc) + return 0; + + cstate = drm_atomic_get_new_crtc_state(state, crtc); + if (!cstate) + return 0; + + ret = drm_atomic_helper_check_plane_state(pstate, cstate, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!pstate->visible) + return 0; + + mode = &cstate->mode; if (fb) { u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); @@ -XXX,XX +XXX,XX @@ static void mcde_setup_dsi(struct mcde *mcde, const struct drm_display_mode *mod *dsi_formatter_frame = formatter_frame; } -static void mcde_display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *cstate, - struct drm_plane_state *plane_state) +static void mcde_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_plane *plane = &pipe->plane; struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); + struct drm_crtc_state *cstate = crtc->state; const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *fb = plane->state->fb; + struct drm_framebuffer *fb = mcde->plane.state->fb; u32 format = fb->format->format; int dsi_pkt_size; int fifo_wtrmrk; @@ -XXX,XX +XXX,XX @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, dev_info(drm->dev, "MCDE display is enabled\n"); } -static void mcde_display_disable(struct drm_simple_display_pipe *pipe) +static void mcde_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); struct drm_pending_vblank_event *event; @@ -XXX,XX +XXX,XX @@ static void mcde_set_extsrc(struct mcde *mcde, u32 buffer_address) writel(buffer_address + mcde->stride, mcde->regs + MCDE_EXTSRCXA1); } -static void mcde_display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_pstate) +static void mcde_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_device *drm = crtc->dev; - struct mcde *mcde = to_mcde(drm); - struct drm_pending_vblank_event *event = crtc->state->event; - struct drm_plane *plane = &pipe->plane; + struct drm_crtc *crtc = plane->state->crtc; + struct drm_device *drm; + struct mcde *mcde; + struct drm_pending_vblank_event *event; struct drm_plane_state *pstate = plane->state; struct drm_framebuffer *fb = pstate->fb; + if (!crtc) + return; + + drm = crtc->dev; + mcde = to_mcde(drm); + event = crtc->state->event; + /* * Handle any pending event first, we need to arm the vblank * interrupt before sending any update to the display so we don't @@ -XXX,XX +XXX,XX @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, } } -static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe) +static int mcde_crtc_enable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); u32 val; @@ -XXX,XX +XXX,XX @@ static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe) +static void mcde_crtc_disable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); @@ -XXX,XX +XXX,XX @@ static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe) writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP); } -static struct drm_simple_display_pipe_funcs mcde_display_funcs = { - .check = mcde_display_check, - .enable = mcde_display_enable, - .disable = mcde_display_disable, - .update = mcde_display_update, - .enable_vblank = mcde_display_enable_vblank, - .disable_vblank = mcde_display_disable_vblank, +static int mcde_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_crtc_funcs mcde_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = mcde_crtc_enable_vblank, + .disable_vblank = mcde_crtc_disable_vblank, +}; + +static const struct drm_crtc_helper_funcs mcde_crtc_helper_funcs = { + .atomic_check = mcde_crtc_helper_atomic_check, + .atomic_enable = mcde_crtc_helper_atomic_enable, + .atomic_disable = mcde_crtc_helper_atomic_disable, +}; + +static const struct drm_plane_funcs mcde_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .reset = drm_atomic_helper_plane_reset, + .destroy = drm_plane_cleanup, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const struct drm_plane_helper_funcs mcde_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = mcde_plane_helper_atomic_check, + .atomic_update = mcde_plane_helper_atomic_update, +}; + +static const struct drm_encoder_funcs mcde_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; int mcde_display_init(struct drm_device *drm) @@ -XXX,XX +XXX,XX @@ int mcde_display_init(struct drm_device *drm) if (ret) return ret; - ret = drm_simple_display_pipe_init(drm, &mcde->pipe, - &mcde_display_funcs, - formats, ARRAY_SIZE(formats), - NULL, - mcde->connector); + ret = drm_universal_plane_init(drm, &mcde->plane, 0, + &mcde_plane_funcs, + formats, ARRAY_SIZE(formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + + drm_plane_helper_add(&mcde->plane, &mcde_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &mcde->crtc, &mcde->plane, + NULL, &mcde_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&mcde->crtc, &mcde_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &mcde->encoder, &mcde_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + + mcde->encoder.possible_crtcs = drm_crtc_mask(&mcde->crtc); + + ret = drm_connector_attach_encoder(mcde->connector, &mcde->encoder); if (ret) return ret; diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/mcde/mcde_drm.h +++ b/drivers/gpu/drm/mcde/mcde_drm.h @@ -XXX,XX +XXX,XX @@ * Parts of this file were based on the MCDE driver by Marcus Lorentzon * (C) ST-Ericsson SA 2013 */ -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_encoder.h> #ifndef _MCDE_DRM_H_ #define _MCDE_DRM_H_ @@ -XXX,XX +XXX,XX @@ struct mcde { struct drm_panel *panel; struct drm_bridge *bridge; struct drm_connector *connector; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct mipi_dsi_device *mdsi; bool dpi_output; s16 stride; diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -XXX,XX +XXX,XX @@ static int mcde_modeset_init(struct drm_device *drm) } /* Attach the bridge. */ - ret = drm_simple_display_pipe_attach_bridge(&mcde->pipe, - mcde->bridge); + ret = drm_bridge_attach(&mcde->encoder, mcde->bridge, NULL, 0); if (ret) { dev_err(drm->dev, "failed to attach display output bridge\n"); return ret; -- 2.55.0
Replace PL111 simple display pipe with explicit plane, CRTC and encoder objects. Keep existing hardware programming and vblank behavior, and install GEM framebuffer prepare helper explicitly. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/pl111/pl111_display.c | 174 ++++++++++++++++++++++++++-------- drivers/gpu/drm/pl111/pl111_drm.h | 5 +- drivers/gpu/drm/pl111/pl111_drv.c | 3 +- 3 files changed, 136 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -XXX,XX +XXX,XX @@ #include <linux/media-bus-format.h> #include <linux/of_graph.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -XXX,XX +XXX,XX @@ irqreturn_t pl111_irq(int irq, void *data) return IRQ_NONE; if (irq_stat & CLCD_IRQ_NEXTBASE_UPDATE) { - drm_crtc_handle_vblank(&priv->pipe.crtc); + drm_crtc_handle_vblank(&priv->crtc); status = IRQ_HANDLED; } @@ -XXX,XX +XXX,XX @@ irqreturn_t pl111_irq(int irq, void *data) } static enum drm_mode_status -pl111_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +pl111_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct drm_device *drm = pipe->crtc.dev; + struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; u32 cpp = DIV_ROUND_UP(priv->variant->fb_depth, 8); u64 bw; @@ -XXX,XX +XXX,XX @@ pl111_mode_valid(struct drm_simple_display_pipe *pipe, return MODE_OK; } -static int pl111_display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *pstate, - struct drm_crtc_state *cstate) +static int pl111_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) { - const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *old_fb = pipe->plane.state->fb; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = pstate->crtc; + struct drm_crtc_state *cstate; + const struct drm_display_mode *mode; + struct drm_framebuffer *old_fb = plane->state->fb; struct drm_framebuffer *fb = pstate->fb; + int ret; + + if (!crtc) + return 0; + + cstate = drm_atomic_get_new_crtc_state(state, crtc); + if (!cstate) + return 0; + + ret = drm_atomic_helper_check_plane_state(pstate, cstate, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!pstate->visible) + return 0; + + mode = &cstate->mode; if (mode->hdisplay % 16) return -EINVAL; @@ -XXX,XX +XXX,XX @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe, return 0; } -static void pl111_display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *cstate, - struct drm_plane_state *plane_state) +static void pl111_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_plane *plane = &pipe->plane; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; + struct drm_crtc_state *cstate = crtc->state; const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *fb = plane->state->fb; + struct drm_framebuffer *fb = priv->plane.state->fb; struct drm_connector *connector = priv->connector; struct drm_bridge *bridge = priv->bridge; bool grayscale = false; @@ -XXX,XX +XXX,XX @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, drm_crtc_vblank_on(crtc); } -static void pl111_display_disable(struct drm_simple_display_pipe *pipe) +static void pl111_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; u32 cntl; @@ -XXX,XX +XXX,XX @@ static void pl111_display_disable(struct drm_simple_display_pipe *pipe) clk_disable_unprepare(priv->clk); } -static void pl111_display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_pstate) +static void pl111_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_device *drm = crtc->dev; - struct pl111_drm_dev_private *priv = drm->dev_private; - struct drm_pending_vblank_event *event = crtc->state->event; - struct drm_plane *plane = &pipe->plane; + struct drm_crtc *crtc = plane->state->crtc; + struct drm_device *drm; + struct pl111_drm_dev_private *priv; + struct drm_pending_vblank_event *event; struct drm_plane_state *pstate = plane->state; struct drm_framebuffer *fb = pstate->fb; + if (!crtc) + return; + + drm = crtc->dev; + priv = drm->dev_private; + event = crtc->state->event; + if (fb) { u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0); @@ -XXX,XX +XXX,XX @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe, } } -static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe) +static int pl111_display_enable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; @@ -XXX,XX +XXX,XX @@ static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void pl111_display_disable_vblank(struct drm_simple_display_pipe *pipe) +static void pl111_display_disable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; writel(0, priv->regs + priv->ienb); } -static struct drm_simple_display_pipe_funcs pl111_display_funcs = { - .mode_valid = pl111_mode_valid, - .check = pl111_display_check, - .enable = pl111_display_enable, - .disable = pl111_display_disable, - .update = pl111_display_update, +static int pl111_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static struct drm_crtc_funcs pl111_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_crtc_helper_funcs pl111_crtc_helper_funcs = { + .mode_valid = pl111_crtc_helper_mode_valid, + .atomic_check = pl111_crtc_helper_atomic_check, + .atomic_enable = pl111_crtc_helper_atomic_enable, + .atomic_disable = pl111_crtc_helper_atomic_disable, +}; + +static const struct drm_plane_funcs pl111_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .reset = drm_atomic_helper_plane_reset, + .destroy = drm_plane_cleanup, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const struct drm_plane_helper_funcs pl111_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = pl111_plane_helper_atomic_check, + .atomic_update = pl111_plane_helper_atomic_update, +}; + +static const struct drm_encoder_funcs pl111_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static int pl111_clk_div_choose_div(struct clk_hw *hw, unsigned long rate, @@ -XXX,XX +XXX,XX @@ int pl111_display_init(struct drm_device *drm) return ret; if (!priv->variant->broken_vblank) { - pl111_display_funcs.enable_vblank = pl111_display_enable_vblank; - pl111_display_funcs.disable_vblank = pl111_display_disable_vblank; + pl111_crtc_funcs.enable_vblank = pl111_display_enable_vblank; + pl111_crtc_funcs.disable_vblank = pl111_display_disable_vblank; } - ret = drm_simple_display_pipe_init(drm, &priv->pipe, - &pl111_display_funcs, - priv->variant->formats, - priv->variant->nformats, - NULL, - priv->connector); + ret = drm_universal_plane_init(drm, &priv->plane, 0, + &pl111_plane_funcs, + priv->variant->formats, + priv->variant->nformats, + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) return ret; + drm_plane_helper_add(&priv->plane, &pl111_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->plane, + NULL, &pl111_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&priv->crtc, &pl111_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &priv->encoder, &pl111_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + + priv->encoder.possible_crtcs = drm_crtc_mask(&priv->crtc); + + if (priv->connector) { + ret = drm_connector_attach_encoder(priv->connector, + &priv->encoder); + if (ret) + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -XXX,XX +XXX,XX @@ #include <drm/drm_encoder.h> #include <drm/drm_gem.h> #include <drm/drm_panel.h> -#include <drm/drm_simple_kms_helper.h> /* * CLCD Controller Internal Register addresses @@ -XXX,XX +XXX,XX @@ struct pl111_drm_dev_private { struct drm_connector *connector; struct drm_panel *panel; struct drm_bridge *bridge; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; void *regs; u32 memory_bw; diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -XXX,XX +XXX,XX @@ static int pl111_modeset_init(struct drm_device *dev) goto out_bridge; } - ret = drm_simple_display_pipe_attach_bridge(&priv->pipe, - bridge); + ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0); if (ret) return ret; -- 2.55.0
Convert gm12u320 to direct primary plane, CRTC and encoder setup. Keep shadow-plane helper state, framebuffer access helpers and no-scaling plane-state check from simple-KMS path. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tiny/gm12u320.c | 128 ++++++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -XXX,XX +XXX,XX @@ #include <linux/usb.h> #include <drm/clients/drm_client_setup.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_connector.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> static bool eco_mode; module_param(eco_mode, bool, 0644); @@ -XXX,XX +XXX,XX @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)"); struct gm12u320_device { struct drm_device dev; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector conn; unsigned char *cmd_buf; unsigned char *data_buf[GM12U320_BLOCK_COUNT]; @@ -XXX,XX +XXX,XX @@ static int gm12u320_conn_init(struct gm12u320_device *gm12u320) } /* ------------------------------------------------------------------ */ -/* gm12u320 (simple) display pipe */ +/* gm12u320 display pipe */ -static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void gm12u320_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT }; - struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev); + struct gm12u320_device *gm12u320 = to_gm12u320(crtc->dev); + struct drm_plane_state *plane_state = crtc->primary->state; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT; gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect); } -static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe) +static void gm12u320_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev); + struct gm12u320_device *gm12u320 = to_gm12u320(crtc->dev); gm12u320_stop_fb_update(gm12u320); } -static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) +static void gm12u320_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct drm_plane_state *state = pipe->plane.state; + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(commit, plane); + struct drm_plane_state *state = plane->state; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); struct drm_rect rect; @@ -XXX,XX +XXX,XX @@ static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe, gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect); } -static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = { - .enable = gm12u320_pipe_enable, - .disable = gm12u320_pipe_disable, - .update = gm12u320_pipe_update, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, +static const struct drm_plane_funcs gm12u320_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +static int gm12u320_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + return ret; +} + +static const struct drm_plane_helper_funcs gm12u320_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = gm12u320_plane_helper_atomic_check, + .atomic_update = gm12u320_plane_helper_atomic_update, +}; + +static int gm12u320_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_crtc_helper_funcs gm12u320_crtc_helper_funcs = { + .atomic_check = gm12u320_crtc_helper_atomic_check, + .atomic_enable = gm12u320_crtc_helper_atomic_enable, + .atomic_disable = gm12u320_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs gm12u320_crtc_funcs = { + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs gm12u320_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static const uint32_t gm12u320_pipe_formats[] = { @@ -XXX,XX +XXX,XX @@ static int gm12u320_usb_probe(struct usb_interface *interface, if (ret) return ret; - ret = drm_simple_display_pipe_init(&gm12u320->dev, - &gm12u320->pipe, - &gm12u320_pipe_funcs, - gm12u320_pipe_formats, - ARRAY_SIZE(gm12u320_pipe_formats), - gm12u320_pipe_modifiers, - &gm12u320->conn); + ret = drm_universal_plane_init(dev, &gm12u320->plane, 0, + &gm12u320_plane_funcs, + gm12u320_pipe_formats, + ARRAY_SIZE(gm12u320_pipe_formats), + gm12u320_pipe_modifiers, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(&gm12u320->plane, &gm12u320_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(dev, &gm12u320->crtc, &gm12u320->plane, NULL, + &gm12u320_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(&gm12u320->crtc, &gm12u320_crtc_helper_funcs); + + ret = drm_encoder_init(dev, &gm12u320->encoder, &gm12u320_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + gm12u320->encoder.possible_crtcs = drm_crtc_mask(&gm12u320->crtc); + + ret = drm_connector_attach_encoder(&gm12u320->conn, &gm12u320->encoder); if (ret) return ret; -- 2.55.0
Convert repaper to explicit primary plane, CRTC and encoder objects. Keep shadow-plane helpers, framebuffer access handling and no-scaling plane-state validation from simple-KMS path. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tiny/repaper.c | 130 +++++++++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -XXX,XX +XXX,XX @@ #include <linux/thermal.h> #include <drm/clients/drm_client_setup.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_rect.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #define REPAPER_RID_G2_COG_ID 0x12 @@ -XXX,XX +XXX,XX @@ enum repaper_epd_border_byte { struct repaper_epd { struct drm_device drm; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; const struct drm_display_mode *mode; struct drm_connector connector; struct spi_device *spi; @@ -XXX,XX +XXX,XX @@ static void power_off(struct repaper_epd *epd) gpiod_set_value_cansleep(epd->discharge, 0); } -static enum drm_mode_status repaper_pipe_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +static enum drm_mode_status repaper_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct drm_crtc *crtc = &pipe->crtc; struct repaper_epd *epd = drm_to_epd(crtc->dev); return drm_crtc_helper_mode_valid_fixed(crtc, mode, epd->mode); } -static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void repaper_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev); + struct repaper_epd *epd = drm_to_epd(crtc->dev); struct spi_device *spi = epd->spi; struct device *dev = &spi->dev; bool dc_ok = false; int i, ret, idx; - if (!drm_dev_enter(pipe->crtc.dev, &idx)) + if (!drm_dev_enter(crtc->dev, &idx)) return; DRM_DEBUG_DRIVER("\n"); @@ -XXX,XX +XXX,XX @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, drm_dev_exit(idx); } -static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) +static void repaper_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev); + struct repaper_epd *epd = drm_to_epd(crtc->dev); struct spi_device *spi = epd->spi; unsigned int line; @@ -XXX,XX +XXX,XX @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) power_off(epd); } -static void repaper_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) +static void repaper_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct drm_plane_state *state = pipe->plane.state; + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(commit, plane); + struct drm_plane_state *state = plane->state; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); struct drm_rect rect; - if (!pipe->crtc.state->active) + if (!state->crtc || !state->crtc->state->active) return; if (drm_atomic_helper_damage_merged(old_state, state, &rect)) @@ -XXX,XX +XXX,XX @@ static void repaper_pipe_update(struct drm_simple_display_pipe *pipe, &shadow_plane_state->fmtcnv_state); } -static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { - .mode_valid = repaper_pipe_mode_valid, - .enable = repaper_pipe_enable, - .disable = repaper_pipe_disable, - .update = repaper_pipe_update, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, +static const struct drm_plane_funcs repaper_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +static int repaper_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + return ret; +} + +static const struct drm_plane_helper_funcs repaper_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = repaper_plane_helper_atomic_check, + .atomic_update = repaper_plane_helper_atomic_update, +}; + +static int repaper_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_crtc_helper_funcs repaper_crtc_helper_funcs = { + .mode_valid = repaper_crtc_helper_mode_valid, + .atomic_check = repaper_crtc_helper_atomic_check, + .atomic_enable = repaper_crtc_helper_atomic_enable, + .atomic_disable = repaper_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs repaper_crtc_funcs = { + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs repaper_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static int repaper_connector_get_modes(struct drm_connector *connector) @@ -XXX,XX +XXX,XX @@ static int repaper_probe(struct spi_device *spi) if (ret) return ret; - ret = drm_simple_display_pipe_init(drm, &epd->pipe, &repaper_pipe_funcs, - repaper_formats, ARRAY_SIZE(repaper_formats), - NULL, &epd->connector); + ret = drm_universal_plane_init(drm, &epd->plane, 0, + &repaper_plane_funcs, + repaper_formats, ARRAY_SIZE(repaper_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(&epd->plane, &repaper_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &epd->crtc, &epd->plane, NULL, + &repaper_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(&epd->crtc, &repaper_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &epd->encoder, &repaper_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + epd->encoder.possible_crtcs = drm_crtc_mask(&epd->crtc); + + ret = drm_connector_attach_encoder(&epd->connector, &epd->encoder); if (ret) return ret; -- 2.55.0
Convert TVE200 to explicit plane, CRTC and encoder objects. Keep generic plane-state validation before TVE200-specific mode, alignment, pitch and format-change checks, and install GEM framebuffer prepare helper explicitly. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tve200/tve200_display.c | 221 ++++++++++++++++++++++---------- drivers/gpu/drm/tve200/tve200_drm.h | 6 +- drivers/gpu/drm/tve200/tve200_drv.c | 17 ++- 3 files changed, 168 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -XXX,XX +XXX,XX @@ #include <linux/of_graph.h> #include <linux/delay.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -XXX,XX +XXX,XX @@ irqreturn_t tve200_irq(int irq, void *data) val = readl(priv->regs + TVE200_CTRL); /* We have an actual start of vsync */ if (!(val & TVE200_VSTSTYPE_BITS)) { - drm_crtc_handle_vblank(&priv->pipe.crtc); + drm_crtc_handle_vblank(&priv->crtc); /* Toggle trigger to start of active image */ val |= TVE200_VSTSTYPE_VAI; } else { @@ -XXX,XX +XXX,XX @@ irqreturn_t tve200_irq(int irq, void *data) return IRQ_HANDLED; } -static int tve200_display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *pstate, - struct drm_crtc_state *cstate) +static int tve200_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) { - const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *old_fb = pipe->plane.state->fb; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = pstate->crtc; + struct drm_crtc_state *cstate = NULL; + const struct drm_display_mode *mode; + struct drm_framebuffer *old_fb = plane->state->fb; struct drm_framebuffer *fb = pstate->fb; + int ret; + + if (crtc) + cstate = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(pstate, cstate, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!pstate->visible) + return 0; + + if (!cstate) + return 0; + + mode = &cstate->mode; /* * We support these specific resolutions and nothing else. @@ -XXX,XX +XXX,XX @@ static int tve200_display_check(struct drm_simple_display_pipe *pipe, return 0; } -static void tve200_display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *cstate, - struct drm_plane_state *plane_state) +static void tve200_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *state) +{ + struct drm_crtc *crtc = plane->state->crtc; + struct drm_device *drm; + struct tve200_drm_dev_private *priv; + struct drm_pending_vblank_event *event; + struct drm_plane_state *pstate = plane->state; + struct drm_framebuffer *fb = pstate->fb; + + if (!crtc) + return; + + drm = crtc->dev; + priv = drm->dev_private; + event = crtc->state->event; + + if (fb) { + /* For RGB, the Y component is used as base address */ + writel(drm_fb_dma_get_gem_addr(fb, pstate, 0), + priv->regs + TVE200_Y_FRAME_BASE_ADDR); + + /* For three plane YUV we need two more addresses */ + if (fb->format->format == DRM_FORMAT_YUV420) { + writel(drm_fb_dma_get_gem_addr(fb, pstate, 1), + priv->regs + TVE200_U_FRAME_BASE_ADDR); + writel(drm_fb_dma_get_gem_addr(fb, pstate, 2), + priv->regs + TVE200_V_FRAME_BASE_ADDR); + } + } + + if (event) { + crtc->state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } +} + +static const struct drm_plane_helper_funcs tve200_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = tve200_plane_helper_atomic_check, + .atomic_update = tve200_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs tve200_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static void tve200_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_plane *plane = &pipe->plane; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(state, crtc); const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *fb = plane->state->fb; + struct drm_plane_state *plane_state = priv->plane.state; + struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector = priv->connector; u32 format = fb->format->format; u32 ctrl1 = 0; @@ -XXX,XX +XXX,XX @@ static void tve200_display_enable(struct drm_simple_display_pipe *pipe, drm_crtc_vblank_on(crtc); } -static void tve200_display_disable(struct drm_simple_display_pipe *pipe) +static void tve200_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; @@ -XXX,XX +XXX,XX @@ static void tve200_display_disable(struct drm_simple_display_pipe *pipe) clk_disable_unprepare(priv->clk); } -static void tve200_display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_pstate) -{ - struct drm_crtc *crtc = &pipe->crtc; - struct drm_device *drm = crtc->dev; - struct tve200_drm_dev_private *priv = drm->dev_private; - struct drm_pending_vblank_event *event = crtc->state->event; - struct drm_plane *plane = &pipe->plane; - struct drm_plane_state *pstate = plane->state; - struct drm_framebuffer *fb = pstate->fb; - - if (fb) { - /* For RGB, the Y component is used as base address */ - writel(drm_fb_dma_get_gem_addr(fb, pstate, 0), - priv->regs + TVE200_Y_FRAME_BASE_ADDR); - - /* For three plane YUV we need two more addresses */ - if (fb->format->format == DRM_FORMAT_YUV420) { - writel(drm_fb_dma_get_gem_addr(fb, pstate, 1), - priv->regs + TVE200_U_FRAME_BASE_ADDR); - writel(drm_fb_dma_get_gem_addr(fb, pstate, 2), - priv->regs + TVE200_V_FRAME_BASE_ADDR); - } - } - - if (event) { - crtc->state->event = NULL; - - spin_lock_irq(&crtc->dev->event_lock); - if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) - drm_crtc_arm_vblank_event(crtc, event); - else - drm_crtc_send_vblank_event(crtc, event); - spin_unlock_irq(&crtc->dev->event_lock); - } -} - -static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe) +static int tve200_crtc_enable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; @@ -XXX,XX +XXX,XX @@ static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void tve200_display_disable_vblank(struct drm_simple_display_pipe *pipe) +static void tve200_crtc_disable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; writel(0, priv->regs + TVE200_INT_EN); } -static const struct drm_simple_display_pipe_funcs tve200_display_funcs = { - .check = tve200_display_check, - .enable = tve200_display_enable, - .disable = tve200_display_disable, - .update = tve200_display_update, - .enable_vblank = tve200_display_enable_vblank, - .disable_vblank = tve200_display_disable_vblank, +static int tve200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_crtc_helper_funcs tve200_crtc_helper_funcs = { + .atomic_check = tve200_crtc_helper_atomic_check, + .atomic_enable = tve200_crtc_helper_atomic_enable, + .atomic_disable = tve200_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs tve200_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = tve200_crtc_enable_vblank, + .disable_vblank = tve200_crtc_disable_vblank, +}; + +static const struct drm_encoder_funcs tve200_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; int tve200_display_init(struct drm_device *drm) @@ -XXX,XX +XXX,XX @@ int tve200_display_init(struct drm_device *drm) DRM_FORMAT_YUV420, }; - ret = drm_simple_display_pipe_init(drm, &priv->pipe, - &tve200_display_funcs, - formats, ARRAY_SIZE(formats), - NULL, - priv->connector); + ret = drm_universal_plane_init(drm, &priv->plane, 0, + &tve200_plane_funcs, + formats, ARRAY_SIZE(formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + + drm_plane_helper_add(&priv->plane, &tve200_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &priv->crtc, + &priv->plane, NULL, + &tve200_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&priv->crtc, &tve200_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &priv->encoder, + &tve200_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); if (ret) return ret; + priv->encoder.possible_crtcs = drm_crtc_mask(&priv->crtc); + return 0; } diff --git a/drivers/gpu/drm/tve200/tve200_drm.h b/drivers/gpu/drm/tve200/tve200_drm.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tve200/tve200_drm.h +++ b/drivers/gpu/drm/tve200/tve200_drm.h @@ -XXX,XX +XXX,XX @@ #include <linux/irqreturn.h> -#include <drm/drm_simple_kms_helper.h> - struct clk; struct drm_bridge; struct drm_connector; @@ -XXX,XX +XXX,XX @@ struct tve200_drm_dev_private { struct drm_connector *connector; struct drm_panel *panel; struct drm_bridge *bridge; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; void *regs; struct clk *pclk; diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -XXX,XX +XXX,XX @@ static int tve200_modeset_init(struct drm_device *dev) goto out_bridge; } - ret = drm_simple_display_pipe_attach_bridge(&priv->pipe, - bridge); + priv->panel = panel; + priv->connector = drm_panel_bridge_connector(bridge); + priv->bridge = bridge; + + ret = drm_connector_attach_encoder(priv->connector, &priv->encoder); if (ret) { - dev_err(dev->dev, "failed to attach bridge\n"); + dev_err(dev->dev, "failed to attach encoder\n"); goto out_bridge; } - priv->panel = panel; - priv->connector = drm_panel_bridge_connector(bridge); - priv->bridge = bridge; + ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0); + if (ret) { + dev_err(dev->dev, "failed to attach bridge\n"); + goto out_bridge; + } dev_info(dev->dev, "attached to panel %s\n", dev_name(panel->dev)); -- 2.55.0
Replace Xen frontend simple display pipe with explicit plane, CRTC and encoder objects for each pipeline. Keep generic plane-state validation before Xen-specific checks, and install GEM framebuffer prepare helper explicitly. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/xen/xen_drm_front.h | 6 +- drivers/gpu/drm/xen/xen_drm_front_kms.c | 177 ++++++++++++++++++++++++-------- 2 files changed, 138 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -XXX,XX +XXX,XX @@ #include <linux/scatterlist.h> #include <drm/drm_connector.h> -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_encoder.h> #include "xen_drm_front_cfg.h" @@ -XXX,XX +XXX,XX @@ struct xen_drm_front_drm_pipeline { int index; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector conn; /* These are only for connector mode checking */ diff --git a/drivers/gpu/drm/xen/xen_drm_front_kms.c b/drivers/gpu/drm/xen/xen_drm_front_kms.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_kms.c +++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c @@ -XXX,XX +XXX,XX @@ #define FRAME_DONE_TO_MS (XEN_DRM_FRONT_WAIT_BACK_MS + 100) static struct xen_drm_front_drm_pipeline * -to_xen_drm_pipeline(struct drm_simple_display_pipe *pipe) +to_xen_drm_pipeline(struct drm_crtc *crtc) { - return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); + return container_of(crtc, struct xen_drm_front_drm_pipeline, crtc); } static void fb_destroy(struct drm_framebuffer *fb) @@ -XXX,XX +XXX,XX @@ static const struct drm_mode_config_funcs mode_config_funcs = { static void send_pending_event(struct xen_drm_front_drm_pipeline *pipeline) { - struct drm_crtc *crtc = &pipeline->pipe.crtc; + struct drm_crtc *crtc = &pipeline->crtc; struct drm_device *dev = crtc->dev; unsigned long flags; @@ -XXX,XX +XXX,XX @@ static void send_pending_event(struct xen_drm_front_drm_pipeline *pipeline) spin_unlock_irqrestore(&dev->event_lock, flags); } -static void display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void xen_drm_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct xen_drm_front_drm_pipeline *pipeline = to_xen_drm_pipeline(crtc); + struct drm_plane_state *plane_state = pipeline->plane.state; struct drm_framebuffer *fb = plane_state->fb; int ret, idx; - if (!drm_dev_enter(pipe->crtc.dev, &idx)) + if (!drm_dev_enter(crtc->dev, &idx)) return; ret = xen_drm_front_mode_set(pipeline, crtc->x, crtc->y, @@ -XXX,XX +XXX,XX @@ static void display_enable(struct drm_simple_display_pipe *pipe, drm_dev_exit(idx); } -static void display_disable(struct drm_simple_display_pipe *pipe) +static void xen_drm_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *state) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); + struct xen_drm_front_drm_pipeline *pipeline = to_xen_drm_pipeline(crtc); int ret = 0, idx; - if (drm_dev_enter(pipe->crtc.dev, &idx)) { + if (drm_dev_enter(crtc->dev, &idx)) { ret = xen_drm_front_mode_set(pipeline, 0, 0, 0, 0, 0, xen_drm_front_fb_to_cookie(NULL)); drm_dev_exit(idx); @@ -XXX,XX +XXX,XX @@ static void pflip_to_worker(struct work_struct *work) send_pending_event(pipeline); } -static bool display_send_page_flip(struct drm_simple_display_pipe *pipe, +static bool display_send_page_flip(struct xen_drm_front_drm_pipeline *pipeline, + struct drm_atomic_commit *state, struct drm_plane_state *old_plane_state) { struct drm_plane_state *plane_state = - drm_atomic_get_new_plane_state(old_plane_state->state, - &pipe->plane); + drm_atomic_get_new_plane_state(state, + &pipeline->plane); /* * If old_plane_state->fb is NULL and plane_state->fb is not, @@ -XXX,XX +XXX,XX @@ static bool display_send_page_flip(struct drm_simple_display_pipe *pipe, * sent to the backend as a part of display_set_config call. */ if (old_plane_state->fb && plane_state->fb) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; int ret; @@ -XXX,XX +XXX,XX @@ static bool display_send_page_flip(struct drm_simple_display_pipe *pipe, return false; } -static int display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state) +static int xen_drm_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) { + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!plane_state->visible) + return 0; + + if (!crtc_state) + return 0; + /* * Xen doesn't initialize vblanking via drm_vblank_init(), so * DRM helpers assume that it doesn't handle vblanking and start @@ -XXX,XX +XXX,XX @@ static int display_check(struct drm_simple_display_pipe *pipe, return 0; } -static void display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_plane_state) +static void xen_drm_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *state) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); + struct drm_crtc *crtc = plane->state->crtc ?: old_plane_state->crtc; + struct xen_drm_front_drm_pipeline *pipeline; struct drm_pending_vblank_event *event; int idx; + if (!crtc) + return; + + pipeline = to_xen_drm_pipeline(crtc); event = crtc->state->event; if (event) { struct drm_device *dev = crtc->dev; @@ -XXX,XX +XXX,XX @@ static void display_update(struct drm_simple_display_pipe *pipe, spin_unlock_irqrestore(&dev->event_lock, flags); } - if (!drm_dev_enter(pipe->crtc.dev, &idx)) { + if (!drm_dev_enter(crtc->dev, &idx)) { send_pending_event(pipeline); return; } @@ -XXX,XX +XXX,XX @@ static void display_update(struct drm_simple_display_pipe *pipe, * If this is not a page flip, e.g. no flip done event from the backend * is expected, then send now. */ - if (!display_send_page_flip(pipe, old_plane_state)) + if (!display_send_page_flip(pipeline, state, old_plane_state)) send_pending_event(pipeline); drm_dev_exit(idx); } static enum drm_mode_status -display_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +xen_drm_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct xen_drm_front_drm_pipeline *pipeline = - container_of(pipe, struct xen_drm_front_drm_pipeline, - pipe); + container_of(crtc, struct xen_drm_front_drm_pipeline, + crtc); if (mode->hdisplay != pipeline->width) return MODE_ERROR; @@ -XXX,XX +XXX,XX @@ display_mode_valid(struct drm_simple_display_pipe *pipe, return MODE_OK; } -static const struct drm_simple_display_pipe_funcs display_funcs = { - .mode_valid = display_mode_valid, - .enable = display_enable, - .disable = display_disable, - .check = display_check, - .update = display_update, +static int xen_drm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + +out: + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_plane_helper_funcs display_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = xen_drm_plane_helper_atomic_check, + .atomic_update = xen_drm_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs display_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const struct drm_crtc_helper_funcs display_crtc_helper_funcs = { + .mode_valid = xen_drm_crtc_helper_mode_valid, + .atomic_check = xen_drm_crtc_helper_atomic_check, + .atomic_enable = xen_drm_crtc_helper_atomic_enable, + .atomic_disable = xen_drm_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs display_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs display_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static int display_pipe_init(struct xen_drm_front_drm_info *drm_info, @@ -XXX,XX +XXX,XX @@ static int display_pipe_init(struct xen_drm_front_drm_info *drm_info, formats = xen_drm_front_conn_get_formats(&format_count); - return drm_simple_display_pipe_init(dev, &pipeline->pipe, - &display_funcs, formats, - format_count, NULL, - &pipeline->conn); + ret = drm_universal_plane_init(dev, &pipeline->plane, 1, + &display_plane_funcs, + formats, format_count, + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + + drm_plane_helper_add(&pipeline->plane, &display_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(dev, &pipeline->crtc, + &pipeline->plane, NULL, + &display_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&pipeline->crtc, &display_crtc_helper_funcs); + + ret = drm_encoder_init(dev, &pipeline->encoder, + &display_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + + pipeline->encoder.possible_crtcs = drm_crtc_mask(&pipeline->crtc); + + ret = drm_connector_attach_encoder(&pipeline->conn, &pipeline->encoder); + if (ret) + return ret; + + return 0; } int xen_drm_front_kms_init(struct xen_drm_front_drm_info *drm_info) -- 2.55.0
struct drm_simple_display_pipe was meant to simplify simple DRM drivers, but instead adds an extra wrapper around normal DRM atomic helper setup. As noted in Documentation/gpu/todo.rst, remaining users should be converted to regular atomic helpers and stop depending on the simple-KMS interfaces. This series converts the following drivers: - arcpgu - aspeed - mcde - pl111 - gm12u320 - repaper - tve200 - xen frontend Each patch replaces drm_simple_display_pipe_init() with explicit primary plane, CRTC and encoder setup, and moves the old simple-pipe callbacks into regular plane and CRTC helper callbacks named according to local driver conventions. The conversions preserve helper behavior that used to be implicit in drm_simple_kms_helper.c, including plane-state validation, CRTC primary-plane checks, affected-plane propagation, framebuffer prepare handling, and existing event/vblank flow where applicable. Result is less helper indirection and more explicit driver-side atomic wiring, with no remaining simple-KMS dependency in these drivers. Except for gm12u320, no hardware testing was performed. This series is based on drm-next-2026-06-27. AI usage disclosure: - I wrote the first two commits myself. The remaining patches were completed with assistance from AI tools. - AI tools were also used to review the code and suggest code changes for the DRM atomic conversion. Thanks, Ze Huang Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- Changes in v2: - common changes: - create upcast helpers - use 'commit' as name of struct drm_atomic_commit in atomic helpers - improve control flow in *_crtc_helper_atomic_check() and *_plane_helper_atomic_check() - Moved page-flip/vblank event handling out of plane update paths and into CRTC atomic_flush(), using atomic_flush and disable paths for mcde, pl111 and tve200 - arcpgu: - remove reduntant mod_supported helper - change obsolete mode field to crtc->state->mode - mcde: - drop attach of unused encoder - tve200: - reorder connector/bridge attach - xen: - change possible_crtcs mask to 0 - Link to v1: https://patch.msgid.link/20260705-drm-simple-kms-removal-v1-0-b4e1ca053623@oss.qualcomm.com --- Ze Huang (8): drm/arcpgu: replace struct drm_simple_display_pipe with regular atomic helpers drm/aspeed: replace struct drm_simple_display_pipe with regular atomic helpers drm/mcde: replace struct drm_simple_display_pipe with regular atomic helpers drm/pl111: replace struct drm_simple_display_pipe with regular atomic helpers drm/gm12u320: replace struct drm_simple_display_pipe with regular atomic helpers drm/repaper: replace struct drm_simple_display_pipe with regular atomic helpers drm/tve200: replace struct drm_simple_display_pipe with regular atomic helpers drm/xen: replace struct drm_simple_display_pipe with regular atomic helpers drivers/gpu/drm/aspeed/aspeed_gfx.h | 11 +- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 187 ++++++++++++++++------- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 3 +- drivers/gpu/drm/mcde/mcde_display.c | 251 ++++++++++++++++++++----------- drivers/gpu/drm/mcde/mcde_drm.h | 8 +- drivers/gpu/drm/mcde/mcde_drv.c | 8 +- drivers/gpu/drm/pl111/pl111_display.c | 202 ++++++++++++++++++------- drivers/gpu/drm/pl111/pl111_drm.h | 5 +- drivers/gpu/drm/pl111/pl111_drv.c | 3 +- drivers/gpu/drm/tiny/arcpgu.c | 179 ++++++++++++++++------ drivers/gpu/drm/tiny/gm12u320.c | 132 +++++++++++++--- drivers/gpu/drm/tiny/repaper.c | 132 ++++++++++++---- drivers/gpu/drm/tve200/tve200_display.c | 217 +++++++++++++++++--------- drivers/gpu/drm/tve200/tve200_drm.h | 6 +- drivers/gpu/drm/tve200/tve200_drv.c | 12 +- drivers/gpu/drm/xen/xen_drm_front.h | 6 +- drivers/gpu/drm/xen/xen_drm_front_kms.c | 175 +++++++++++++++------ 17 files changed, 1107 insertions(+), 430 deletions(-) --- base-commit: 3696d07837d1df13a5603d77f667685e7dfb3c53 change-id: 20260704-drm-simple-kms-removal-01a031c6a129 Best regards, -- Ze Huang <ze.huang@oss.qualcomm.com>
Instantiate plane, CRTC and encoder directly and wire them up with standard atomic helpers. This removes arcpgu's dependency on deprecated simple-KMS display pipe interface. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tiny/arcpgu.c | 179 +++++++++++++++++++++++++++++++----------- 1 file changed, 133 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tiny/arcpgu.c +++ b/drivers/gpu/drm/tiny/arcpgu.c @@ -XXX,XX +XXX,XX @@ #include <linux/clk.h> #include <drm/clients/drm_client_setup.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_debugfs.h> #include <drm/drm_device.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_fbdev_dma.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> +#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_of.h> +#include <drm/drm_plane.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/of_reserved_mem.h> @@ -XXX,XX +XXX,XX @@ struct arcpgu_drm_private { struct drm_device drm; void __iomem *regs; struct clk *clk; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector sim_conn; }; -#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm) - -#define pipe_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe) +static inline struct arcpgu_drm_private *dev_to_arcpgu(struct drm_device *drm) +{ + return container_of(drm, struct arcpgu_drm_private, drm); +} static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, unsigned int reg, u32 value) @@ -XXX,XX +XXX,XX @@ static const u32 arc_pgu_supported_formats[] = { static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) { - const struct drm_framebuffer *fb = arcpgu->pipe.plane.state->fb; + const struct drm_framebuffer *fb = arcpgu->plane.state->fb; uint32_t pixel_format = fb->format->format; u32 format = DRM_FORMAT_INVALID; int i; @@ -XXX,XX +XXX,XX @@ static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, reg_ctrl); } -static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +static enum drm_mode_status arcpgu_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(crtc->dev); long rate, clk_rate = mode->clock * 1000; long diff = clk_rate / 200; /* +-0.5% allowed by HDMI spec */ @@ -XXX,XX +XXX,XX @@ static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *p static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) { - struct drm_display_mode *m = &arcpgu->pipe.crtc.state->adjusted_mode; + struct drm_display_mode *m = &arcpgu->crtc.state->adjusted_mode; u32 val; arc_pgu_write(arcpgu, ARCPGU_REG_FMT, @@ -XXX,XX +XXX,XX @@ static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu) clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); } -static void arc_pgu_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void arcpgu_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(crtc->dev); arc_pgu_mode_set(arcpgu); @@ -XXX,XX +XXX,XX @@ static void arc_pgu_enable(struct drm_simple_display_pipe *pipe, ARCPGU_CTRL_ENABLE_MASK); } -static void arc_pgu_disable(struct drm_simple_display_pipe *pipe) +static void arcpgu_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe); + struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(crtc->dev); clk_disable_unprepare(arcpgu->clk); arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, @@ -XXX,XX +XXX,XX @@ static void arc_pgu_disable(struct drm_simple_display_pipe *pipe) ~ARCPGU_CTRL_ENABLE_MASK); } -static void arc_pgu_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *state) +static void arcpgu_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); struct arcpgu_drm_private *arcpgu; struct drm_gem_dma_object *gem; - if (!pipe->plane.state->fb) + if (!pstate->fb) return; - arcpgu = pipe_to_arcpgu_priv(pipe); - gem = drm_fb_dma_get_gem_obj(pipe->plane.state->fb, 0); + arcpgu = dev_to_arcpgu(plane->dev); + gem = drm_fb_dma_get_gem_obj(pstate->fb, 0); arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->dma_addr); } -static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = { - .update = arc_pgu_update, - .mode_valid = arc_pgu_mode_valid, - .enable = arc_pgu_enable, - .disable = arc_pgu_disable, -}; - static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { - .fb_create = drm_gem_fb_create, + .fb_create = drm_gem_fb_create, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, }; DEFINE_DRM_GEM_DMA_FOPS(arcpgu_drm_ops); +static int arcpgu_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *commit) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); +} + +static const struct drm_plane_helper_funcs arcpgu_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = arcpgu_plane_helper_atomic_check, + .atomic_update = arcpgu_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs arcpgu_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static int arcpgu_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, crtc); +} + +static const struct drm_crtc_helper_funcs arcpgu_crtc_helper_funcs = { + .mode_valid = arcpgu_crtc_helper_mode_valid, + .atomic_check = arcpgu_crtc_helper_atomic_check, + .atomic_enable = arcpgu_crtc_helper_atomic_enable, + .atomic_disable = arcpgu_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs arcpgu_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs arcpgu_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + static int arcpgu_load(struct arcpgu_drm_private *arcpgu) { struct platform_device *pdev = to_platform_device(arcpgu->drm.dev); @@ -XXX,XX +XXX,XX @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) struct device_node *endpoint_node = NULL; struct drm_connector *connector = NULL; struct drm_device *drm = &arcpgu->drm; + struct drm_plane *plane; + struct drm_encoder *encoder; + struct drm_crtc *crtc; int ret; arcpgu->clk = devm_clk_get(drm->dev, "pxlclk"); @@ -XXX,XX +XXX,XX @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32))) return -ENODEV; + plane = &arcpgu->plane; + ret = drm_universal_plane_init(drm, plane, 0, + &arcpgu_plane_funcs, + arc_pgu_supported_formats, + ARRAY_SIZE(arc_pgu_supported_formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(plane, &arcpgu_plane_helper_funcs); + + crtc = &arcpgu->crtc; + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, + &arcpgu_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(crtc, &arcpgu_crtc_helper_funcs); + + encoder = &arcpgu->encoder; + ret = drm_encoder_init(drm, encoder, &arcpgu_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + encoder->possible_crtcs = drm_crtc_mask(crtc); + /* * There is only one output port inside each device. It is linked with * encoder endpoint. @@ -XXX,XX +XXX,XX @@ static int arcpgu_load(struct arcpgu_drm_private *arcpgu) if (endpoint_node) { encoder_node = of_graph_get_remote_port_parent(endpoint_node); of_node_put(endpoint_node); - } else { - connector = &arcpgu->sim_conn; - dev_info(drm->dev, "no encoder found. Assumed virtual LCD on simulation platform\n"); - ret = arcpgu_drm_sim_init(drm, connector); - if (ret < 0) - return ret; - } - ret = drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs, - arc_pgu_supported_formats, - ARRAY_SIZE(arc_pgu_supported_formats), - NULL, connector); - if (ret) - return ret; - - if (encoder_node) { /* Locate drm bridge from the hdmi encoder DT node */ struct drm_bridge *bridge __free(drm_bridge_put) = of_drm_find_and_get_bridge(encoder_node); if (!bridge) return -EPROBE_DEFER; - ret = drm_simple_display_pipe_attach_bridge(&arcpgu->pipe, bridge); + ret = drm_bridge_attach(encoder, bridge, NULL, 0); + if (ret) + return ret; + } else { + connector = &arcpgu->sim_conn; + dev_info(drm->dev, "no encoder found. Assumed virtual LCD on simulation platform\n"); + ret = arcpgu_drm_sim_init(drm, connector); + if (ret < 0) + return ret; + + ret = drm_connector_attach_encoder(connector, encoder); if (ret) return ret; } @@ -XXX,XX +XXX,XX @@ static int arcpgu_show_pxlclock(struct seq_file *m, void *arg) struct drm_device *drm = node->minor->dev; struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm); unsigned long clkrate = clk_get_rate(arcpgu->clk); - unsigned long mode_clock = arcpgu->pipe.crtc.mode.crtc_clock * 1000; + unsigned long mode_clock = arcpgu->crtc.state->mode.crtc_clock * 1000; seq_printf(m, "hw : %lu\n", clkrate); seq_printf(m, "mode: %lu\n", mode_clock); -- 2.43.0
Replace simple display pipe with explicit plane, CRTC and encoder objects. Move callbacks to plane and CRTC helpers, with vblank handling through drm_crtc_funcs. Move page-flip event handling out of the plane update path and into the CRTC atomic flush path. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/aspeed/aspeed_gfx.h | 11 +- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 187 ++++++++++++++++++++++--------- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 3 +- 3 files changed, 145 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx.h b/drivers/gpu/drm/aspeed/aspeed_gfx.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx.h +++ b/drivers/gpu/drm/aspeed/aspeed_gfx.h @@ -XXX,XX +XXX,XX @@ /* Copyright 2018 IBM Corporation */ #include <drm/drm_device.h> -#include <drm/drm_simple_kms_helper.h> struct aspeed_gfx { struct drm_device drm; @@ -XXX,XX +XXX,XX @@ struct aspeed_gfx { u32 throd_val; u32 scan_line_max; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector connector; }; -#define to_aspeed_gfx(x) container_of(x, struct aspeed_gfx, drm) + +static struct aspeed_gfx *to_aspeed_gfx(struct drm_device *drm) +{ + return container_of(drm, struct aspeed_gfx, drm); +} int aspeed_gfx_create_pipe(struct drm_device *drm); int aspeed_gfx_create_output(struct drm_device *drm); diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -XXX,XX +XXX,XX @@ #include <linux/reset.h> #include <linux/regmap.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_device.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_panel.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> #include "aspeed_gfx.h" -static struct aspeed_gfx * -drm_pipe_to_aspeed_gfx(struct drm_simple_display_pipe *pipe) -{ - return container_of(pipe, struct aspeed_gfx, pipe); -} - static int aspeed_gfx_set_pixel_fmt(struct aspeed_gfx *priv, u32 *bpp) { - struct drm_crtc *crtc = &priv->pipe.crtc; + struct drm_crtc *crtc = &priv->crtc; struct drm_device *drm = crtc->dev; - const u32 format = crtc->primary->state->fb->format->format; + const u32 format = priv->plane.state->fb->format->format; u32 ctrl1; ctrl1 = readl(priv->base + CRT_CTRL1); @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_disable_controller(struct aspeed_gfx *priv) static void aspeed_gfx_crtc_mode_set_nofb(struct aspeed_gfx *priv) { - struct drm_display_mode *m = &priv->pipe.crtc.state->adjusted_mode; + struct drm_display_mode *m = &priv->crtc.state->adjusted_mode; u32 ctrl1, d_offset, t_count, bpp; int err; @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_crtc_mode_set_nofb(struct aspeed_gfx *priv) writel(priv->throd_val, priv->base + CRT_THROD); } -static void aspeed_gfx_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void aspeed_gfx_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct aspeed_gfx *priv = to_aspeed_gfx(crtc->dev); aspeed_gfx_crtc_mode_set_nofb(priv); aspeed_gfx_enable_controller(priv); drm_crtc_vblank_on(crtc); } -static void aspeed_gfx_pipe_disable(struct drm_simple_display_pipe *pipe) +static void aspeed_gfx_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct aspeed_gfx *priv = to_aspeed_gfx(crtc->dev); drm_crtc_vblank_off(crtc); aspeed_gfx_disable_controller(priv); } -static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state) +static void aspeed_gfx_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); - struct drm_crtc *crtc = &pipe->crtc; - struct drm_framebuffer *fb = pipe->plane.state->fb; - struct drm_pending_vblank_event *event; + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(commit, plane); + struct aspeed_gfx *priv = to_aspeed_gfx(plane->dev); + struct drm_framebuffer *fb = new_plane_state->fb; struct drm_gem_dma_object *gem; - spin_lock_irq(&crtc->dev->event_lock); - event = crtc->state->event; - if (event) { - crtc->state->event = NULL; - - if (drm_crtc_vblank_get(crtc) == 0) - drm_crtc_arm_vblank_event(crtc, event); - else - drm_crtc_send_vblank_event(crtc, event); - } - spin_unlock_irq(&crtc->dev->event_lock); - if (!fb) return; @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, writel(gem->dma_addr, priv->base + CRT_ADDR); } -static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe) +static int aspeed_gfx_crtc_enable_vblank(struct drm_crtc *crtc) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); + struct aspeed_gfx *priv = to_aspeed_gfx(crtc->dev); u32 reg = readl(priv->base + CRT_CTRL1); /* Clear pending VBLANK IRQ */ @@ -XXX,XX +XXX,XX @@ static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void aspeed_gfx_disable_vblank(struct drm_simple_display_pipe *pipe) +static void aspeed_gfx_crtc_disable_vblank(struct drm_crtc *crtc) { - struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); + struct aspeed_gfx *priv = to_aspeed_gfx(crtc->dev); u32 reg = readl(priv->base + CRT_CTRL1); reg &= ~CRT_CTRL_VERTICAL_INTR_EN; @@ -XXX,XX +XXX,XX @@ static void aspeed_gfx_disable_vblank(struct drm_simple_display_pipe *pipe) writel(reg | CRT_CTRL_VERTICAL_INTR_STS, priv->base + CRT_CTRL1); } -static const struct drm_simple_display_pipe_funcs aspeed_gfx_funcs = { - .enable = aspeed_gfx_pipe_enable, - .disable = aspeed_gfx_pipe_disable, - .update = aspeed_gfx_pipe_update, - .enable_vblank = aspeed_gfx_enable_vblank, - .disable_vblank = aspeed_gfx_disable_vblank, +static int aspeed_gfx_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *commit) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); +} + +static const struct drm_plane_helper_funcs aspeed_gfx_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = aspeed_gfx_plane_helper_atomic_check, + .atomic_update = aspeed_gfx_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs aspeed_gfx_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static int aspeed_gfx_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, crtc); +} + +static void aspeed_gfx_crtc_helper_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + struct drm_pending_vblank_event *event = new_crtc_state->event; + + if (!event) + return; + + new_crtc_state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); +} + +static const struct drm_crtc_helper_funcs aspeed_gfx_crtc_helper_funcs = { + .atomic_check = aspeed_gfx_crtc_helper_atomic_check, + .atomic_enable = aspeed_gfx_crtc_helper_atomic_enable, + .atomic_disable = aspeed_gfx_crtc_helper_atomic_disable, + .atomic_flush = aspeed_gfx_crtc_helper_atomic_flush, +}; + +static const struct drm_crtc_funcs aspeed_gfx_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = aspeed_gfx_crtc_enable_vblank, + .disable_vblank = aspeed_gfx_crtc_disable_vblank, +}; + +static const struct drm_encoder_funcs aspeed_gfx_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static const uint32_t aspeed_gfx_formats[] = { @@ -XXX,XX +XXX,XX @@ static const uint32_t aspeed_gfx_formats[] = { int aspeed_gfx_create_pipe(struct drm_device *drm) { struct aspeed_gfx *priv = to_aspeed_gfx(drm); + struct drm_plane *plane = &priv->plane; + struct drm_crtc *crtc = &priv->crtc; + struct drm_encoder *encoder = &priv->encoder; + int ret; + + ret = drm_universal_plane_init(drm, plane, 0, + &aspeed_gfx_plane_funcs, + aspeed_gfx_formats, + ARRAY_SIZE(aspeed_gfx_formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(plane, &aspeed_gfx_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, + &aspeed_gfx_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(crtc, &aspeed_gfx_crtc_helper_funcs); + + ret = drm_encoder_init(drm, encoder, &aspeed_gfx_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + encoder->possible_crtcs = drm_crtc_mask(crtc); + + ret = drm_connector_attach_encoder(&priv->connector, encoder); + if (ret) + return ret; - return drm_simple_display_pipe_init(drm, &priv->pipe, &aspeed_gfx_funcs, - aspeed_gfx_formats, - ARRAY_SIZE(aspeed_gfx_formats), - NULL, - &priv->connector); + return 0; } diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -XXX,XX +XXX,XX @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> #include <drm/drm_drv.h> @@ -XXX,XX +XXX,XX @@ static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data) reg = readl(priv->base + CRT_CTRL1); if (reg & CRT_CTRL_VERTICAL_INTR_STS) { - drm_crtc_handle_vblank(&priv->pipe.crtc); + drm_crtc_handle_vblank(&priv->crtc); writel(reg, priv->base + priv->int_clr_reg); return IRQ_HANDLED; } -- 2.43.0
Convert MCDE to explicit plane, CRTC and encoder objects. Handle pending page-flip events from the CRTC atomic flush path using the commit-local CRTC state, and avoid manual connector/encoder attachment before the connector has been created by the bridge path. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/mcde/mcde_display.c | 251 +++++++++++++++++++++++------------- drivers/gpu/drm/mcde/mcde_drm.h | 8 +- drivers/gpu/drm/mcde/mcde_drv.c | 8 +- 3 files changed, 173 insertions(+), 94 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -XXX,XX +XXX,XX @@ #include <linux/regulator/consumer.h> #include <linux/media-bus-format.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_device.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_gem_dma_helper.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_print.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_vblank.h> #include <video/mipi_display.h> @@ -XXX,XX +XXX,XX @@ void mcde_display_irq(struct mcde *mcde) writel(mispp, mcde->regs + MCDE_RISPP); if (vblank) - drm_crtc_handle_vblank(&mcde->pipe.crtc); + drm_crtc_handle_vblank(&mcde->crtc); if (misovl) dev_info(mcde->dev, "some stray overlay IRQ %08x\n", misovl); @@ -XXX,XX +XXX,XX @@ void mcde_display_disable_irqs(struct mcde *mcde) writel(0xFFFFFFFF, mcde->regs + MCDE_RISCHNL); } -static int mcde_display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *pstate, - struct drm_crtc_state *cstate) +static int mcde_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *old_fb = pipe->plane.state->fb; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); + struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(commit, plane); + struct drm_crtc *crtc = pstate->crtc; + struct drm_crtc_state *cstate = NULL; + const struct drm_display_mode *mode; + struct drm_framebuffer *old_fb = old_pstate->fb; struct drm_framebuffer *fb = pstate->fb; + int ret; - if (fb) { - u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); + if (crtc) + cstate = drm_atomic_get_new_crtc_state(commit, crtc); - /* FB base address must be dword aligned. */ - if (offset & 3) { - DRM_DEBUG_KMS("FB not 32-bit aligned\n"); - return -EINVAL; - } + ret = drm_atomic_helper_check_plane_state(pstate, cstate, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; - /* - * There's no pitch register, the mode's hdisplay - * controls this. - */ - if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) { - DRM_DEBUG_KMS("can't handle pitches\n"); - return -EINVAL; - } + if (!pstate->visible || !fb) + return 0; - /* - * We can't change the FB format in a flicker-free - * manner (and only update it during CRTC enable). - */ - if (old_fb && old_fb->format != fb->format) - cstate->mode_changed = true; + mode = &cstate->mode; + + u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); + + /* FB base address must be dword aligned. */ + if (offset & 3) { + DRM_DEBUG_KMS("FB not 32-bit aligned\n"); + return -EINVAL; + } + + /* + * There's no pitch register, the mode's hdisplay + * controls this. + */ + if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) { + DRM_DEBUG_KMS("can't handle pitches\n"); + return -EINVAL; } + /* + * We can't change the FB format in a flicker-free + * manner (and only update it during CRTC enable). + */ + if (old_fb && old_fb->format != fb->format) + cstate->mode_changed = true; + return 0; } @@ -XXX,XX +XXX,XX @@ static void mcde_setup_dsi(struct mcde *mcde, const struct drm_display_mode *mod *dsi_formatter_frame = formatter_frame; } -static void mcde_display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *cstate, - struct drm_plane_state *plane_state) +static void mcde_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_plane *plane = &pipe->plane; struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc); + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, &mcde->plane); const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *fb = plane->state->fb; + struct drm_framebuffer *fb = plane_state->fb; u32 format = fb->format->format; int dsi_pkt_size; int fifo_wtrmrk; @@ -XXX,XX +XXX,XX @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, dev_info(drm->dev, "MCDE display is enabled\n"); } -static void mcde_display_disable(struct drm_simple_display_pipe *pipe) +static void mcde_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc); struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); struct drm_pending_vblank_event *event; @@ -XXX,XX +XXX,XX @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) mcde_dsi_disable(mcde->bridge); } - event = crtc->state->event; + event = cstate->event; if (event) { - crtc->state->event = NULL; + cstate->event = NULL; spin_lock_irq(&crtc->dev->event_lock); drm_crtc_send_vblank_event(crtc, event); @@ -XXX,XX +XXX,XX @@ static void mcde_set_extsrc(struct mcde *mcde, u32 buffer_address) writel(buffer_address + mcde->stride, mcde->regs + MCDE_EXTSRCXA1); } -static void mcde_display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_pstate) +static void mcde_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_device *drm = crtc->dev; - struct mcde *mcde = to_mcde(drm); - struct drm_pending_vblank_event *event = crtc->state->event; - struct drm_plane *plane = &pipe->plane; - struct drm_plane_state *pstate = plane->state; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); + struct mcde *mcde = to_mcde(plane->dev); struct drm_framebuffer *fb = pstate->fb; - /* - * Handle any pending event first, we need to arm the vblank - * interrupt before sending any update to the display so we don't - * miss the interrupt. - */ - if (event) { - crtc->state->event = NULL; - - spin_lock_irq(&crtc->dev->event_lock); - /* - * Hardware must be on before we can arm any vblank event, - * this is not a scanout controller where there is always - * some periodic update going on, it is completely frozen - * until we get an update. If MCDE output isn't yet enabled, - * we just send a vblank dummy event back. - */ - if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) { - dev_dbg(mcde->dev, "arm vblank event\n"); - drm_crtc_arm_vblank_event(crtc, event); - } else { - dev_dbg(mcde->dev, "insert fake vblank event\n"); - drm_crtc_send_vblank_event(crtc, event); - } - - spin_unlock_irq(&crtc->dev->event_lock); - } - /* * We do not start sending framebuffer updates before the * display is enabled. Update events will however be dispatched @@ -XXX,XX +XXX,XX @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, } } -static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe) +static void mcde_crtc_helper_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + struct drm_pending_vblank_event *event = crtc_state->event; + + /* + * Handle any pending event first, we need to arm the vblank + * interrupt before sending any update to the display so we don't + * miss the interrupt. + */ + if (!event) + return; + + crtc_state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + /* + * Hardware must be on before we can arm any vblank event, + * this is not a scanout controller where there is always + * some periodic update going on, it is completely frozen + * until we get an update. If MCDE output isn't yet enabled, + * we just send a vblank dummy event back. + */ + if (crtc_state->active && drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + + spin_unlock_irq(&crtc->dev->event_lock); +} + +static int mcde_crtc_enable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); u32 val; @@ -XXX,XX +XXX,XX @@ static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe) +static void mcde_crtc_disable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); @@ -XXX,XX +XXX,XX @@ static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe) writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP); } -static struct drm_simple_display_pipe_funcs mcde_display_funcs = { - .check = mcde_display_check, - .enable = mcde_display_enable, - .disable = mcde_display_disable, - .update = mcde_display_update, - .enable_vblank = mcde_display_enable_vblank, - .disable_vblank = mcde_display_disable_vblank, +static int mcde_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, crtc); +} + +static const struct drm_crtc_funcs mcde_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = mcde_crtc_enable_vblank, + .disable_vblank = mcde_crtc_disable_vblank, +}; + +static const struct drm_crtc_helper_funcs mcde_crtc_helper_funcs = { + .atomic_check = mcde_crtc_helper_atomic_check, + .atomic_enable = mcde_crtc_helper_atomic_enable, + .atomic_disable = mcde_crtc_helper_atomic_disable, + .atomic_flush = mcde_crtc_helper_atomic_flush, +}; + +static const struct drm_plane_funcs mcde_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .reset = drm_atomic_helper_plane_reset, + .destroy = drm_plane_cleanup, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const struct drm_plane_helper_funcs mcde_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = mcde_plane_helper_atomic_check, + .atomic_update = mcde_plane_helper_atomic_update, +}; + +static const struct drm_encoder_funcs mcde_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; int mcde_display_init(struct drm_device *drm) @@ -XXX,XX +XXX,XX @@ int mcde_display_init(struct drm_device *drm) if (ret) return ret; - ret = drm_simple_display_pipe_init(drm, &mcde->pipe, - &mcde_display_funcs, - formats, ARRAY_SIZE(formats), - NULL, - mcde->connector); + ret = drm_universal_plane_init(drm, &mcde->plane, 0, + &mcde_plane_funcs, + formats, ARRAY_SIZE(formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + + drm_plane_helper_add(&mcde->plane, &mcde_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &mcde->crtc, &mcde->plane, + NULL, &mcde_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&mcde->crtc, &mcde_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &mcde->encoder, &mcde_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); if (ret) return ret; + mcde->encoder.possible_crtcs = drm_crtc_mask(&mcde->crtc); + return 0; } EXPORT_SYMBOL_GPL(mcde_display_init); diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/mcde/mcde_drm.h +++ b/drivers/gpu/drm/mcde/mcde_drm.h @@ -XXX,XX +XXX,XX @@ * Parts of this file were based on the MCDE driver by Marcus Lorentzon * (C) ST-Ericsson SA 2013 */ -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_encoder.h> #ifndef _MCDE_DRM_H_ #define _MCDE_DRM_H_ @@ -XXX,XX +XXX,XX @@ struct mcde { struct drm_panel *panel; struct drm_bridge *bridge; struct drm_connector *connector; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct mipi_dsi_device *mdsi; bool dpi_output; s16 stride; @@ -XXX,XX +XXX,XX @@ struct mcde { struct regulator *vana; }; -#define to_mcde(dev) container_of(dev, struct mcde, drm) +struct mcde *to_mcde(struct drm_device *dev); static inline bool mcde_flow_is_video(struct mcde *mcde) { diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -XXX,XX +XXX,XX @@ static const struct drm_mode_config_helper_funcs mcde_mode_config_helpers = { .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, }; +struct mcde *to_mcde(struct drm_device *dev) +{ + return container_of(dev, struct mcde, drm); +} + static irqreturn_t mcde_irq(int irq, void *data) { struct mcde *mcde = data; @@ -XXX,XX +XXX,XX @@ static int mcde_modeset_init(struct drm_device *drm) } /* Attach the bridge. */ - ret = drm_simple_display_pipe_attach_bridge(&mcde->pipe, - mcde->bridge); + ret = drm_bridge_attach(&mcde->encoder, mcde->bridge, NULL, 0); if (ret) { dev_err(drm->dev, "failed to attach display output bridge\n"); return ret; -- 2.43.0
Replace PL111 simple display pipe with explicit plane, CRTC and encoder objects. Keep the existing PL111 timing, format and pitch validation, but move it into the explicit atomic check paths. Move event handling to the CRTC commit path. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/pl111/pl111_display.c | 202 ++++++++++++++++++++++++---------- drivers/gpu/drm/pl111/pl111_drm.h | 5 +- drivers/gpu/drm/pl111/pl111_drv.c | 3 +- 3 files changed, 150 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -XXX,XX +XXX,XX @@ #include <linux/media-bus-format.h> #include <linux/of_graph.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -XXX,XX +XXX,XX @@ irqreturn_t pl111_irq(int irq, void *data) return IRQ_NONE; if (irq_stat & CLCD_IRQ_NEXTBASE_UPDATE) { - drm_crtc_handle_vblank(&priv->pipe.crtc); + drm_crtc_handle_vblank(&priv->crtc); status = IRQ_HANDLED; } @@ -XXX,XX +XXX,XX @@ irqreturn_t pl111_irq(int irq, void *data) } static enum drm_mode_status -pl111_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +pl111_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct drm_device *drm = pipe->crtc.dev; + struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; u32 cpp = DIV_ROUND_UP(priv->variant->fb_depth, 8); u64 bw; @@ -XXX,XX +XXX,XX @@ pl111_mode_valid(struct drm_simple_display_pipe *pipe, return MODE_OK; } -static int pl111_display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *pstate, - struct drm_crtc_state *cstate) +static int pl111_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *old_fb = pipe->plane.state->fb; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); + struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(commit, plane); + struct drm_crtc *crtc = pstate->crtc; + struct drm_crtc_state *cstate = NULL; + const struct drm_display_mode *mode; + struct drm_framebuffer *old_fb = old_pstate->fb; struct drm_framebuffer *fb = pstate->fb; + int ret; + + if (crtc) + cstate = drm_atomic_get_new_crtc_state(commit, crtc); + + ret = drm_atomic_helper_check_plane_state(pstate, cstate, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!pstate->visible) + return 0; + + mode = &cstate->mode; if (mode->hdisplay % 16) return -EINVAL; @@ -XXX,XX +XXX,XX @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe, return 0; } -static void pl111_display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *cstate, - struct drm_plane_state *plane_state) +static void pl111_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_plane *plane = &pipe->plane; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc); const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *fb = plane->state->fb; + struct drm_framebuffer *fb = priv->plane.state->fb; struct drm_connector *connector = priv->connector; struct drm_bridge *bridge = priv->bridge; bool grayscale = false; @@ -XXX,XX +XXX,XX @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, drm_crtc_vblank_on(crtc); } -static void pl111_display_disable(struct drm_simple_display_pipe *pipe) +static void pl111_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; u32 cntl; @@ -XXX,XX +XXX,XX @@ static void pl111_display_disable(struct drm_simple_display_pipe *pipe) clk_disable_unprepare(priv->clk); } -static void pl111_display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_pstate) +static void pl111_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_device *drm = crtc->dev; - struct pl111_drm_dev_private *priv = drm->dev_private; - struct drm_pending_vblank_event *event = crtc->state->event; - struct drm_plane *plane = &pipe->plane; - struct drm_plane_state *pstate = plane->state; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); + struct drm_crtc *crtc = pstate->crtc; + struct drm_device *drm; + struct pl111_drm_dev_private *priv; struct drm_framebuffer *fb = pstate->fb; - if (fb) { - u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0); + if (!fb) + return; - writel(addr, priv->regs + CLCD_UBAS); - } + drm = crtc->dev; + priv = drm->dev_private; - if (event) { - crtc->state->event = NULL; + u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0); - spin_lock_irq(&crtc->dev->event_lock); - if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) - drm_crtc_arm_vblank_event(crtc, event); - else - drm_crtc_send_vblank_event(crtc, event); - spin_unlock_irq(&crtc->dev->event_lock); - } + writel(addr, priv->regs + CLCD_UBAS); +} + +static void pl111_crtc_helper_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc); + struct drm_pending_vblank_event *event = cstate->event; + + if (!event) + return; + + cstate->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + if (cstate->active && drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); } -static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe) +static int pl111_display_enable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; @@ -XXX,XX +XXX,XX @@ static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void pl111_display_disable_vblank(struct drm_simple_display_pipe *pipe) +static void pl111_display_disable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; writel(0, priv->regs + priv->ienb); } -static struct drm_simple_display_pipe_funcs pl111_display_funcs = { - .mode_valid = pl111_mode_valid, - .check = pl111_display_check, - .enable = pl111_display_enable, - .disable = pl111_display_disable, - .update = pl111_display_update, +static int pl111_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, crtc); +} + +static struct drm_crtc_funcs pl111_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_crtc_helper_funcs pl111_crtc_helper_funcs = { + .mode_valid = pl111_crtc_helper_mode_valid, + .atomic_check = pl111_crtc_helper_atomic_check, + .atomic_enable = pl111_crtc_helper_atomic_enable, + .atomic_disable = pl111_crtc_helper_atomic_disable, + .atomic_flush = pl111_crtc_helper_atomic_flush, +}; + +static const struct drm_plane_funcs pl111_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .reset = drm_atomic_helper_plane_reset, + .destroy = drm_plane_cleanup, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const struct drm_plane_helper_funcs pl111_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = pl111_plane_helper_atomic_check, + .atomic_update = pl111_plane_helper_atomic_update, +}; + +static const struct drm_encoder_funcs pl111_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static int pl111_clk_div_choose_div(struct clk_hw *hw, unsigned long rate, @@ -XXX,XX +XXX,XX @@ int pl111_display_init(struct drm_device *drm) return ret; if (!priv->variant->broken_vblank) { - pl111_display_funcs.enable_vblank = pl111_display_enable_vblank; - pl111_display_funcs.disable_vblank = pl111_display_disable_vblank; + pl111_crtc_funcs.enable_vblank = pl111_display_enable_vblank; + pl111_crtc_funcs.disable_vblank = pl111_display_disable_vblank; } - ret = drm_simple_display_pipe_init(drm, &priv->pipe, - &pl111_display_funcs, - priv->variant->formats, - priv->variant->nformats, - NULL, - priv->connector); + ret = drm_universal_plane_init(drm, &priv->plane, 0, + &pl111_plane_funcs, + priv->variant->formats, + priv->variant->nformats, + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + + drm_plane_helper_add(&priv->plane, &pl111_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->plane, + NULL, &pl111_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&priv->crtc, &pl111_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &priv->encoder, &pl111_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); if (ret) return ret; + priv->encoder.possible_crtcs = drm_crtc_mask(&priv->crtc); + + if (priv->connector) { + ret = drm_connector_attach_encoder(priv->connector, + &priv->encoder); + if (ret) + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -XXX,XX +XXX,XX @@ #include <drm/drm_encoder.h> #include <drm/drm_gem.h> #include <drm/drm_panel.h> -#include <drm/drm_simple_kms_helper.h> /* * CLCD Controller Internal Register addresses @@ -XXX,XX +XXX,XX @@ struct pl111_drm_dev_private { struct drm_connector *connector; struct drm_panel *panel; struct drm_bridge *bridge; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; void *regs; u32 memory_bw; diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -XXX,XX +XXX,XX @@ static int pl111_modeset_init(struct drm_device *dev) goto out_bridge; } - ret = drm_simple_display_pipe_attach_bridge(&priv->pipe, - bridge); + ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0); if (ret) return ret; -- 2.43.0
Convert gm12u320 to direct primary plane, CRTC and encoder setup. Keep shadow-plane helper state, framebuffer access helpers and no-scaling plane-state check from simple-KMS path. Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tiny/gm12u320.c | 132 ++++++++++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -XXX,XX +XXX,XX @@ #include <linux/usb.h> #include <drm/clients/drm_client_setup.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_connector.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> static bool eco_mode; module_param(eco_mode, bool, 0644); @@ -XXX,XX +XXX,XX @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)"); struct gm12u320_device { struct drm_device dev; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector conn; unsigned char *cmd_buf; unsigned char *data_buf[GM12U320_BLOCK_COUNT]; @@ -XXX,XX +XXX,XX @@ struct gm12u320_device { } fb_update; }; -#define to_gm12u320(__dev) container_of(__dev, struct gm12u320_device, dev) +static struct gm12u320_device *to_gm12u320(struct drm_device *__dev) +{ + return container_of(__dev, struct gm12u320_device, dev); +} static const char cmd_data[CMD_SIZE] = { 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, @@ -XXX,XX +XXX,XX @@ static int gm12u320_conn_init(struct gm12u320_device *gm12u320) } /* ------------------------------------------------------------------ */ -/* gm12u320 (simple) display pipe */ +/* gm12u320 display pipe */ -static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void gm12u320_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT }; - struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev); + struct gm12u320_device *gm12u320 = to_gm12u320(crtc->dev); + struct drm_plane_state *plane_state = gm12u320->plane.state; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT; gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect); } -static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe) +static void gm12u320_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev); + struct gm12u320_device *gm12u320 = to_gm12u320(crtc->dev); gm12u320_stop_fb_update(gm12u320); } -static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) +static void gm12u320_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct drm_plane_state *state = pipe->plane.state; + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(commit, plane); + struct drm_plane_state *state = drm_atomic_get_new_plane_state(commit, plane); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); struct drm_rect rect; + if (!state->fb) + return; + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect); } -static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = { - .enable = gm12u320_pipe_enable, - .disable = gm12u320_pipe_disable, - .update = gm12u320_pipe_update, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, +static const struct drm_plane_funcs gm12u320_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +static int gm12u320_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *commit) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); +} + +static const struct drm_plane_helper_funcs gm12u320_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = gm12u320_plane_helper_atomic_check, + .atomic_update = gm12u320_plane_helper_atomic_update, +}; + +static int gm12u320_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, crtc); +} + +static const struct drm_crtc_helper_funcs gm12u320_crtc_helper_funcs = { + .atomic_check = gm12u320_crtc_helper_atomic_check, + .atomic_enable = gm12u320_crtc_helper_atomic_enable, + .atomic_disable = gm12u320_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs gm12u320_crtc_funcs = { + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs gm12u320_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static const uint32_t gm12u320_pipe_formats[] = { @@ -XXX,XX +XXX,XX @@ static int gm12u320_usb_probe(struct usb_interface *interface, if (ret) return ret; - ret = drm_simple_display_pipe_init(&gm12u320->dev, - &gm12u320->pipe, - &gm12u320_pipe_funcs, - gm12u320_pipe_formats, - ARRAY_SIZE(gm12u320_pipe_formats), - gm12u320_pipe_modifiers, - &gm12u320->conn); + ret = drm_universal_plane_init(dev, &gm12u320->plane, 0, + &gm12u320_plane_funcs, + gm12u320_pipe_formats, + ARRAY_SIZE(gm12u320_pipe_formats), + gm12u320_pipe_modifiers, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(&gm12u320->plane, &gm12u320_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(dev, &gm12u320->crtc, &gm12u320->plane, NULL, + &gm12u320_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(&gm12u320->crtc, &gm12u320_crtc_helper_funcs); + + ret = drm_encoder_init(dev, &gm12u320->encoder, &gm12u320_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + gm12u320->encoder.possible_crtcs = drm_crtc_mask(&gm12u320->crtc); + + ret = drm_connector_attach_encoder(&gm12u320->conn, &gm12u320->encoder); if (ret) return ret; -- 2.43.0
Convert repaper to explicit primary plane, CRTC and encoder objects. Keep shadow-plane helpers, framebuffer access handling and no-scaling plane-state validation from simple-KMS path. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tiny/repaper.c | 132 ++++++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -XXX,XX +XXX,XX @@ #include <linux/thermal.h> #include <drm/clients/drm_client_setup.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> @@ -XXX,XX +XXX,XX @@ #include <drm/drm_rect.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #define REPAPER_RID_G2_COG_ID 0x12 @@ -XXX,XX +XXX,XX @@ enum repaper_epd_border_byte { struct repaper_epd { struct drm_device drm; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; const struct drm_display_mode *mode; struct drm_connector connector; struct spi_device *spi; @@ -XXX,XX +XXX,XX @@ static void power_off(struct repaper_epd *epd) gpiod_set_value_cansleep(epd->discharge, 0); } -static enum drm_mode_status repaper_pipe_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +static enum drm_mode_status repaper_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct drm_crtc *crtc = &pipe->crtc; struct repaper_epd *epd = drm_to_epd(crtc->dev); return drm_crtc_helper_mode_valid_fixed(crtc, mode, epd->mode); } -static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void repaper_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev); + struct repaper_epd *epd = drm_to_epd(crtc->dev); struct spi_device *spi = epd->spi; struct device *dev = &spi->dev; bool dc_ok = false; int i, ret, idx; - if (!drm_dev_enter(pipe->crtc.dev, &idx)) + if (!drm_dev_enter(crtc->dev, &idx)) return; DRM_DEBUG_DRIVER("\n"); @@ -XXX,XX +XXX,XX @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, drm_dev_exit(idx); } -static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) +static void repaper_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct repaper_epd *epd = drm_to_epd(pipe->crtc.dev); + struct repaper_epd *epd = drm_to_epd(crtc->dev); struct spi_device *spi = epd->spi; unsigned int line; @@ -XXX,XX +XXX,XX @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) power_off(epd); } -static void repaper_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) +static void repaper_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct drm_plane_state *state = pipe->plane.state; - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); + struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(commit, plane); + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(pstate); struct drm_rect rect; - if (!pipe->crtc.state->active) + if (!pstate->fb) return; - if (drm_atomic_helper_damage_merged(old_state, state, &rect)) - repaper_fb_dirty(state->fb, shadow_plane_state->data, + if (drm_atomic_helper_damage_merged(old_pstate, pstate, &rect)) + repaper_fb_dirty(pstate->fb, shadow_plane_state->data, &shadow_plane_state->fmtcnv_state); } -static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { - .mode_valid = repaper_pipe_mode_valid, - .enable = repaper_pipe_enable, - .disable = repaper_pipe_disable, - .update = repaper_pipe_update, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, +static const struct drm_plane_funcs repaper_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +static int repaper_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *state) +{ + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); +} + +static const struct drm_plane_helper_funcs repaper_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = repaper_plane_helper_atomic_check, + .atomic_update = repaper_plane_helper_atomic_update, +}; + +static int repaper_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_commit *state) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(state, crtc); +} + +static const struct drm_crtc_helper_funcs repaper_crtc_helper_funcs = { + .mode_valid = repaper_crtc_helper_mode_valid, + .atomic_check = repaper_crtc_helper_atomic_check, + .atomic_enable = repaper_crtc_helper_atomic_enable, + .atomic_disable = repaper_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs repaper_crtc_funcs = { + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs repaper_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static int repaper_connector_get_modes(struct drm_connector *connector) @@ -XXX,XX +XXX,XX @@ static int repaper_probe(struct spi_device *spi) if (ret) return ret; - ret = drm_simple_display_pipe_init(drm, &epd->pipe, &repaper_pipe_funcs, - repaper_formats, ARRAY_SIZE(repaper_formats), - NULL, &epd->connector); + ret = drm_universal_plane_init(drm, &epd->plane, 0, + &repaper_plane_funcs, + repaper_formats, ARRAY_SIZE(repaper_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(&epd->plane, &repaper_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &epd->crtc, &epd->plane, NULL, + &repaper_crtc_funcs, NULL); + if (ret) + return ret; + drm_crtc_helper_add(&epd->crtc, &repaper_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &epd->encoder, &repaper_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + epd->encoder.possible_crtcs = drm_crtc_mask(&epd->crtc); + + ret = drm_connector_attach_encoder(&epd->connector, &epd->encoder); if (ret) return ret; -- 2.43.0
Convert TVE200 to explicit plane, CRTC and encoder objects. Keep generic plane-state validation before TVE200-specific mode, alignment, pitch and format-change checks, and install GEM framebuffer prepare helper explicitly. Move page-flip event handling to the CRTC commit path and wire the CRTC vblank callbacks explicitly so events are not consumed from the plane update path. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/tve200/tve200_display.c | 217 ++++++++++++++++++++++---------- drivers/gpu/drm/tve200/tve200_drm.h | 6 +- drivers/gpu/drm/tve200/tve200_drv.c | 12 +- 3 files changed, 161 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -XXX,XX +XXX,XX @@ #include <linux/of_graph.h> #include <linux/delay.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -XXX,XX +XXX,XX @@ irqreturn_t tve200_irq(int irq, void *data) val = readl(priv->regs + TVE200_CTRL); /* We have an actual start of vsync */ if (!(val & TVE200_VSTSTYPE_BITS)) { - drm_crtc_handle_vblank(&priv->pipe.crtc); + drm_crtc_handle_vblank(&priv->crtc); /* Toggle trigger to start of active image */ val |= TVE200_VSTSTYPE_VAI; } else { @@ -XXX,XX +XXX,XX @@ irqreturn_t tve200_irq(int irq, void *data) return IRQ_HANDLED; } -static int tve200_display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *pstate, - struct drm_crtc_state *cstate) +static int tve200_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *old_fb = pipe->plane.state->fb; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); + struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(commit, plane); + struct drm_crtc *crtc = pstate->crtc; + struct drm_crtc_state *cstate = NULL; + const struct drm_display_mode *mode; + struct drm_framebuffer *old_fb = old_pstate->fb; struct drm_framebuffer *fb = pstate->fb; + int ret; + + if (crtc) + cstate = drm_atomic_get_new_crtc_state(commit, crtc); + + ret = drm_atomic_helper_check_plane_state(pstate, cstate, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!pstate->visible || !cstate) + return 0; + + mode = &cstate->mode; /* * We support these specific resolutions and nothing else. @@ -XXX,XX +XXX,XX @@ static int tve200_display_check(struct drm_simple_display_pipe *pipe, return 0; } -static void tve200_display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *cstate, - struct drm_plane_state *plane_state) +static void tve200_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) +{ + struct tve200_drm_dev_private *priv = plane->dev->dev_private; + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane); + struct drm_framebuffer *fb = pstate->fb; + + if (!fb) + return; + + /* For RGB, the Y component is used as base address */ + writel(drm_fb_dma_get_gem_addr(fb, pstate, 0), + priv->regs + TVE200_Y_FRAME_BASE_ADDR); + + /* For three plane YUV we need two more addresses */ + if (fb->format->format == DRM_FORMAT_YUV420) { + writel(drm_fb_dma_get_gem_addr(fb, pstate, 1), + priv->regs + TVE200_U_FRAME_BASE_ADDR); + writel(drm_fb_dma_get_gem_addr(fb, pstate, 2), + priv->regs + TVE200_V_FRAME_BASE_ADDR); + } +} + +static void tve200_crtc_helper_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc); + struct drm_pending_vblank_event *event = cstate->event; + + if (!event) + return; + + cstate->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + if (cstate->active && drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); +} + +static const struct drm_plane_helper_funcs tve200_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = tve200_plane_helper_atomic_check, + .atomic_update = tve200_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs tve200_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static void tve200_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; - struct drm_plane *plane = &pipe->plane; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc); const struct drm_display_mode *mode = &cstate->mode; - struct drm_framebuffer *fb = plane->state->fb; + struct drm_plane_state *plane_state = priv->plane.state; + struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector = priv->connector; u32 format = fb->format->format; u32 ctrl1 = 0; @@ -XXX,XX +XXX,XX @@ static void tve200_display_enable(struct drm_simple_display_pipe *pipe, drm_crtc_vblank_on(crtc); } -static void tve200_display_disable(struct drm_simple_display_pipe *pipe) +static void tve200_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; @@ -XXX,XX +XXX,XX @@ static void tve200_display_disable(struct drm_simple_display_pipe *pipe) clk_disable_unprepare(priv->clk); } -static void tve200_display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_pstate) -{ - struct drm_crtc *crtc = &pipe->crtc; - struct drm_device *drm = crtc->dev; - struct tve200_drm_dev_private *priv = drm->dev_private; - struct drm_pending_vblank_event *event = crtc->state->event; - struct drm_plane *plane = &pipe->plane; - struct drm_plane_state *pstate = plane->state; - struct drm_framebuffer *fb = pstate->fb; - - if (fb) { - /* For RGB, the Y component is used as base address */ - writel(drm_fb_dma_get_gem_addr(fb, pstate, 0), - priv->regs + TVE200_Y_FRAME_BASE_ADDR); - - /* For three plane YUV we need two more addresses */ - if (fb->format->format == DRM_FORMAT_YUV420) { - writel(drm_fb_dma_get_gem_addr(fb, pstate, 1), - priv->regs + TVE200_U_FRAME_BASE_ADDR); - writel(drm_fb_dma_get_gem_addr(fb, pstate, 2), - priv->regs + TVE200_V_FRAME_BASE_ADDR); - } - } - - if (event) { - crtc->state->event = NULL; - - spin_lock_irq(&crtc->dev->event_lock); - if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) - drm_crtc_arm_vblank_event(crtc, event); - else - drm_crtc_send_vblank_event(crtc, event); - spin_unlock_irq(&crtc->dev->event_lock); - } -} - -static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe) +static int tve200_crtc_enable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; @@ -XXX,XX +XXX,XX @@ static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe) return 0; } -static void tve200_display_disable_vblank(struct drm_simple_display_pipe *pipe) +static void tve200_crtc_disable_vblank(struct drm_crtc *crtc) { - struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; writel(0, priv->regs + TVE200_INT_EN); } -static const struct drm_simple_display_pipe_funcs tve200_display_funcs = { - .check = tve200_display_check, - .enable = tve200_display_enable, - .disable = tve200_display_disable, - .update = tve200_display_update, - .enable_vblank = tve200_display_enable_vblank, - .disable_vblank = tve200_display_disable_vblank, +static int tve200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, crtc); +} + +static const struct drm_crtc_helper_funcs tve200_crtc_helper_funcs = { + .atomic_check = tve200_crtc_helper_atomic_check, + .atomic_enable = tve200_crtc_helper_atomic_enable, + .atomic_disable = tve200_crtc_helper_atomic_disable, + .atomic_flush = tve200_crtc_helper_atomic_flush, +}; + +static const struct drm_crtc_funcs tve200_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = tve200_crtc_enable_vblank, + .disable_vblank = tve200_crtc_disable_vblank, +}; + +static const struct drm_encoder_funcs tve200_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; int tve200_display_init(struct drm_device *drm) @@ -XXX,XX +XXX,XX @@ int tve200_display_init(struct drm_device *drm) DRM_FORMAT_YUV420, }; - ret = drm_simple_display_pipe_init(drm, &priv->pipe, - &tve200_display_funcs, - formats, ARRAY_SIZE(formats), - NULL, - priv->connector); + ret = drm_universal_plane_init(drm, &priv->plane, 0, + &tve200_plane_funcs, + formats, ARRAY_SIZE(formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) return ret; + drm_plane_helper_add(&priv->plane, &tve200_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &priv->crtc, + &priv->plane, NULL, + &tve200_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&priv->crtc, &tve200_crtc_helper_funcs); + + ret = drm_encoder_init(drm, &priv->encoder, + &tve200_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + + priv->encoder.possible_crtcs = drm_crtc_mask(&priv->crtc); + return 0; } diff --git a/drivers/gpu/drm/tve200/tve200_drm.h b/drivers/gpu/drm/tve200/tve200_drm.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tve200/tve200_drm.h +++ b/drivers/gpu/drm/tve200/tve200_drm.h @@ -XXX,XX +XXX,XX @@ #include <linux/irqreturn.h> -#include <drm/drm_simple_kms_helper.h> - struct clk; struct drm_bridge; struct drm_connector; @@ -XXX,XX +XXX,XX @@ struct tve200_drm_dev_private { struct drm_connector *connector; struct drm_panel *panel; struct drm_bridge *bridge; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; void *regs; struct clk *pclk; diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -XXX,XX +XXX,XX @@ static int tve200_modeset_init(struct drm_device *dev) goto out_bridge; } - ret = drm_simple_display_pipe_attach_bridge(&priv->pipe, - bridge); + priv->panel = panel; + priv->bridge = bridge; + + ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0); if (ret) { dev_err(dev->dev, "failed to attach bridge\n"); goto out_bridge; } - priv->panel = panel; priv->connector = drm_panel_bridge_connector(bridge); - priv->bridge = bridge; + if (!priv->connector) { + ret = -ENODEV; + goto out_bridge; + } dev_info(dev->dev, "attached to panel %s\n", dev_name(panel->dev)); -- 2.43.0
Replace Xen frontend simple display pipe with explicit plane, CRTC and encoder objects for each pipeline. Keep generic plane-state validation before Xen-specific checks, and install GEM framebuffer prepare helper explicitly. Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com> --- drivers/gpu/drm/xen/xen_drm_front.h | 6 +- drivers/gpu/drm/xen/xen_drm_front_kms.c | 175 ++++++++++++++++++++++++-------- 2 files changed, 134 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -XXX,XX +XXX,XX @@ #include <linux/scatterlist.h> #include <drm/drm_connector.h> -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_encoder.h> #include "xen_drm_front_cfg.h" @@ -XXX,XX +XXX,XX @@ struct xen_drm_front_drm_pipeline { int index; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector conn; /* These are only for connector mode checking */ diff --git a/drivers/gpu/drm/xen/xen_drm_front_kms.c b/drivers/gpu/drm/xen/xen_drm_front_kms.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_kms.c +++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c @@ -XXX,XX +XXX,XX @@ #define FRAME_DONE_TO_MS (XEN_DRM_FRONT_WAIT_BACK_MS + 100) static struct xen_drm_front_drm_pipeline * -to_xen_drm_pipeline(struct drm_simple_display_pipe *pipe) +xen_drm_pipeline_from_crtc(struct drm_crtc *crtc) { - return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); + return container_of(crtc, struct xen_drm_front_drm_pipeline, crtc); +} + +static struct xen_drm_front_drm_pipeline * +xen_drm_pipeline_from_plane(struct drm_plane *plane) +{ + return container_of(plane, struct xen_drm_front_drm_pipeline, plane); } static void fb_destroy(struct drm_framebuffer *fb) @@ -XXX,XX +XXX,XX @@ static const struct drm_mode_config_funcs mode_config_funcs = { static void send_pending_event(struct xen_drm_front_drm_pipeline *pipeline) { - struct drm_crtc *crtc = &pipeline->pipe.crtc; + struct drm_crtc *crtc = &pipeline->crtc; struct drm_device *dev = crtc->dev; unsigned long flags; @@ -XXX,XX +XXX,XX @@ static void send_pending_event(struct xen_drm_front_drm_pipeline *pipeline) spin_unlock_irqrestore(&dev->event_lock, flags); } -static void display_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static void xen_drm_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_crtc(crtc); + struct drm_plane_state *plane_state = pipeline->plane.state; struct drm_framebuffer *fb = plane_state->fb; int ret, idx; - if (!drm_dev_enter(pipe->crtc.dev, &idx)) + if (!drm_dev_enter(crtc->dev, &idx)) return; ret = xen_drm_front_mode_set(pipeline, crtc->x, crtc->y, fb->width, fb->height, fb->format->cpp[0] * 8, xen_drm_front_fb_to_cookie(fb)); - if (ret) { DRM_ERROR("Failed to enable display: %d\n", ret); pipeline->conn_connected = false; @@ -XXX,XX +XXX,XX @@ static void display_enable(struct drm_simple_display_pipe *pipe, drm_dev_exit(idx); } -static void display_disable(struct drm_simple_display_pipe *pipe) +static void xen_drm_crtc_helper_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_commit *commit) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_crtc(crtc); int ret = 0, idx; - if (drm_dev_enter(pipe->crtc.dev, &idx)) { + if (drm_dev_enter(crtc->dev, &idx)) { ret = xen_drm_front_mode_set(pipeline, 0, 0, 0, 0, 0, xen_drm_front_fb_to_cookie(NULL)); drm_dev_exit(idx); @@ -XXX,XX +XXX,XX @@ static void pflip_to_worker(struct work_struct *work) send_pending_event(pipeline); } -static bool display_send_page_flip(struct drm_simple_display_pipe *pipe, +static bool display_send_page_flip(struct xen_drm_front_drm_pipeline *pipeline, + struct drm_atomic_commit *commit, struct drm_plane_state *old_plane_state) { struct drm_plane_state *plane_state = - drm_atomic_get_new_plane_state(old_plane_state->state, - &pipe->plane); + drm_atomic_get_new_plane_state(commit, + &pipeline->plane); /* * If old_plane_state->fb is NULL and plane_state->fb is not, @@ -XXX,XX +XXX,XX @@ static bool display_send_page_flip(struct drm_simple_display_pipe *pipe, * sent to the backend as a part of display_set_config call. */ if (old_plane_state->fb && plane_state->fb) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; int ret; @@ -XXX,XX +XXX,XX @@ static bool display_send_page_flip(struct drm_simple_display_pipe *pipe, return false; } -static int display_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state) +static int xen_drm_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_commit *commit) { + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, plane); + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!plane_state->visible || !crtc_state) + return 0; + /* * Xen doesn't initialize vblanking via drm_vblank_init(), so * DRM helpers assume that it doesn't handle vblanking and start @@ -XXX,XX +XXX,XX @@ static int display_check(struct drm_simple_display_pipe *pipe, return 0; } -static void display_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_plane_state) +static void xen_drm_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_commit *commit) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); - struct drm_crtc *crtc = &pipe->crtc; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(commit, plane); + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_plane(plane); + struct drm_crtc *crtc = &pipeline->crtc; struct drm_pending_vblank_event *event; int idx; @@ -XXX,XX +XXX,XX @@ static void display_update(struct drm_simple_display_pipe *pipe, spin_unlock_irqrestore(&dev->event_lock, flags); } - if (!drm_dev_enter(pipe->crtc.dev, &idx)) { + if (!drm_dev_enter(crtc->dev, &idx)) { send_pending_event(pipeline); return; } @@ -XXX,XX +XXX,XX @@ static void display_update(struct drm_simple_display_pipe *pipe, * If this is not a page flip, e.g. no flip done event from the backend * is expected, then send now. */ - if (!display_send_page_flip(pipe, old_plane_state)) + if (!display_send_page_flip(pipeline, commit, old_plane_state)) send_pending_event(pipeline); drm_dev_exit(idx); } static enum drm_mode_status -display_mode_valid(struct drm_simple_display_pipe *pipe, - const struct drm_display_mode *mode) +xen_drm_crtc_helper_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct xen_drm_front_drm_pipeline *pipeline = - container_of(pipe, struct xen_drm_front_drm_pipeline, - pipe); + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_crtc(crtc); if (mode->hdisplay != pipeline->width) return MODE_ERROR; @@ -XXX,XX +XXX,XX @@ display_mode_valid(struct drm_simple_display_pipe *pipe, return MODE_OK; } -static const struct drm_simple_display_pipe_funcs display_funcs = { - .mode_valid = display_mode_valid, - .enable = display_enable, - .disable = display_disable, - .check = display_check, - .update = display_update, +static int xen_drm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, crtc); +} + +static const struct drm_plane_helper_funcs display_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .atomic_check = xen_drm_plane_helper_atomic_check, + .atomic_update = xen_drm_plane_helper_atomic_update, +}; + +static const struct drm_plane_funcs display_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const struct drm_crtc_helper_funcs display_crtc_helper_funcs = { + .mode_valid = xen_drm_crtc_helper_mode_valid, + .atomic_check = xen_drm_crtc_helper_atomic_check, + .atomic_enable = xen_drm_crtc_helper_atomic_enable, + .atomic_disable = xen_drm_crtc_helper_atomic_disable, +}; + +static const struct drm_crtc_funcs display_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static const struct drm_encoder_funcs display_encoder_funcs = { + .destroy = drm_encoder_cleanup, }; static int display_pipe_init(struct xen_drm_front_drm_info *drm_info, @@ -XXX,XX +XXX,XX @@ static int display_pipe_init(struct xen_drm_front_drm_info *drm_info, formats = xen_drm_front_conn_get_formats(&format_count); - return drm_simple_display_pipe_init(dev, &pipeline->pipe, - &display_funcs, formats, - format_count, NULL, - &pipeline->conn); + ret = drm_universal_plane_init(dev, &pipeline->plane, 0, + &display_plane_funcs, + formats, format_count, + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + + drm_plane_helper_add(&pipeline->plane, &display_plane_helper_funcs); + + ret = drm_crtc_init_with_planes(dev, &pipeline->crtc, + &pipeline->plane, NULL, + &display_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&pipeline->crtc, &display_crtc_helper_funcs); + + ret = drm_encoder_init(dev, &pipeline->encoder, + &display_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; + + pipeline->encoder.possible_crtcs = drm_crtc_mask(&pipeline->crtc); + + ret = drm_connector_attach_encoder(&pipeline->conn, &pipeline->encoder); + if (ret) + return ret; + + return 0; } int xen_drm_front_kms_init(struct xen_drm_front_drm_info *drm_info) -- 2.43.0