Use drmm_kzalloc() to align encoder memory lifetime with the drm device, and use drmm_add_action_or_reset() to make sure drm_encoder_cleanup() is called before the memory is freed. Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> Acked-by: Daniel Vetter <daniel.vetter@xxxxxxxx> --- Changes since v1: - Split some changes out into previous patches. --- drivers/gpu/drm/imx/imx-tve.c | 54 +++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index aa1c2ab34170..bac025eafa1f 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -19,6 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> @@ -99,9 +100,13 @@ enum { TVE_MODE_VGA, }; -struct imx_tve { +struct imx_tve_encoder { struct drm_connector connector; struct drm_encoder encoder; + struct imx_tve *tve; +}; + +struct imx_tve { struct device *dev; int mode; int di_hsync_pin; @@ -118,12 +123,12 @@ struct imx_tve { static inline struct imx_tve *con_to_tve(struct drm_connector *c) { - return container_of(c, struct imx_tve, connector); + return container_of(c, struct imx_tve_encoder, connector)->tve; } static inline struct imx_tve *enc_to_tve(struct drm_encoder *e) { - return container_of(e, struct imx_tve, encoder); + return container_of(e, struct imx_tve_encoder, encoder)->tve; } static void tve_enable(struct imx_tve *tve) @@ -428,6 +433,13 @@ static int tve_clk_init(struct imx_tve *tve, void __iomem *base) return 0; } +static void imx_tve_encoder_cleanup(struct drm_device *drm, void *ptr) +{ + struct drm_encoder *encoder = ptr; + + drm_encoder_cleanup(encoder); +} + static void imx_tve_disable_regulator(void *data) { struct imx_tve *tve = data; @@ -477,33 +489,45 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data) { struct drm_device *drm = data; struct imx_tve *tve = dev_get_drvdata(dev); - struct drm_encoder *encoder = &tve->encoder; - struct drm_connector *connector = &tve->connector; + struct imx_tve_encoder *tvee; + struct drm_encoder *encoder; + struct drm_connector *connector; int encoder_type; int ret; encoder_type = tve->mode == TVE_MODE_VGA ? DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC; - memset(connector, 0, sizeof(*connector)); - memset(encoder, 0, sizeof(*encoder)); + tvee = drmm_kzalloc(drm, sizeof(*tvee), GFP_KERNEL); + if (!tvee) + return -ENOMEM; + + tvee->tve = tve; + encoder = &tvee->encoder; + connector = &tvee->connector; + + ret = drm_simple_encoder_init(drm, encoder, encoder_type); + if (ret) + return ret; + + ret = drmm_add_action_or_reset(drm, imx_tve_encoder_cleanup, encoder); + if (ret) + return ret; ret = imx_drm_encoder_parse_of(drm, encoder, tve->dev->of_node); if (ret) return ret; drm_encoder_helper_add(encoder, &imx_tve_encoder_helper_funcs); - drm_simple_encoder_init(drm, encoder, encoder_type); drm_connector_helper_add(connector, &imx_tve_connector_helper_funcs); - drm_connector_init_with_ddc(drm, connector, - &imx_tve_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - tve->ddc); - - drm_connector_attach_encoder(connector, encoder); + ret = drm_connector_init_with_ddc(drm, connector, + &imx_tve_connector_funcs, + DRM_MODE_CONNECTOR_VGA, tve->ddc); + if (ret) + return ret; - return 0; + return drm_connector_attach_encoder(connector, encoder); } static const struct component_ops imx_tve_ops = { -- 2.20.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel