diff mbox series

[v4,40/78] drm/vc4: hdmi: rework connectors and encoders

Message ID 6ff9f5156dd14ab23967fe7357660b3cbf556c22.1594230107.git-series.maxime@cerno.tech (mailing list archive)
State New, archived
Headers show
Series drm/vc4: Support BCM2711 Display Pipeline | expand

Commit Message

Maxime Ripard July 8, 2020, 5:41 p.m. UTC
the vc4_hdmi driver has some custom structures to hold the data it needs to
associate with the drm_encoder and drm_connector structures.

However, it allocates them separately from the vc4_hdmi structure which
makes it more complicated than it needs to be.

Move those structures to be contained by vc4_hdmi and update the code
accordingly.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
 2 files changed, 72 insertions(+), 79 deletions(-)

Comments

Dave Stevenson July 28, 2020, 11:58 a.m. UTC | #1
Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> the vc4_hdmi driver has some custom structures to hold the data it needs to
> associate with the drm_encoder and drm_connector structures.
>
> However, it allocates them separately from the vc4_hdmi structure which
> makes it more complicated than it needs to be.
>
> Move those structures to be contained by vc4_hdmi and update the code
> accordingly.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
>  2 files changed, 72 insertions(+), 79 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index db79e0d88625..1e2214f24ed7 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
>         .get_modes = vc4_hdmi_connector_get_modes,
>  };
>
> -static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
> -                                                    struct drm_encoder *encoder,
> -                                                    struct i2c_adapter *ddc)
> +static int vc4_hdmi_connector_init(struct drm_device *dev,
> +                                  struct vc4_hdmi *vc4_hdmi,
> +                                  struct i2c_adapter *ddc)
>  {
> -       struct drm_connector *connector;
> -       struct vc4_hdmi_connector *hdmi_connector;
> +       struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
> +       struct drm_connector *connector = &hdmi_connector->base;
> +       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
>         int ret;
>
> -       hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
> -                                     GFP_KERNEL);
> -       if (!hdmi_connector)
> -               return ERR_PTR(-ENOMEM);
> -       connector = &hdmi_connector->base;
> -
>         hdmi_connector->encoder = encoder;
>
>         drm_connector_init_with_ddc(dev, connector,
> @@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>         /* Create and attach TV margin props to this connector. */
>         ret = drm_mode_create_tv_margin_properties(dev);
>         if (ret)
> -               return ERR_PTR(ret);
> +               return ret;
>
>         drm_connector_attach_tv_margin_properties(connector);
>
> @@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>
>         drm_connector_attach_encoder(connector, encoder);
>
> -       return connector;
> +       return 0;
>  }
>
>  static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
> @@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         struct vc4_dev *vc4 = encoder->dev->dev_private;
>         struct vc4_hdmi *hdmi = vc4->hdmi;
> -       struct drm_connector_state *cstate = hdmi->connector->state;
> +       struct drm_connector *connector = &hdmi->connector.base;
> +       struct drm_connector_state *cstate = connector->state;
>         struct drm_crtc *crtc = encoder->crtc;
>         const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         union hdmi_infoframe frame;
>         int ret;
>
>         ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -                                                      hdmi->connector, mode);
> +                                                      connector, mode);
>         if (ret < 0) {
>                 DRM_ERROR("couldn't fill AVI infoframe\n");
>                 return;
>         }
>
>         drm_hdmi_avi_infoframe_quant_range(&frame.avi,
> -                                          hdmi->connector, mode,
> +                                          connector, mode,
>                                            vc4_encoder->limited_rgb_range ?
>                                            HDMI_QUANTIZATION_RANGE_LIMITED :
>                                            HDMI_QUANTIZATION_RANGE_FULL);
> @@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
>  /* HDMI audio codec callbacks */
>  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_device *drm = hdmi->encoder->dev;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>         u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
>         unsigned long n, m;
> @@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_crtc *crtc = encoder->crtc;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_connector *connector = &hdmi->connector.base;
>         struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
>         int ret;
>
> @@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                 VC4_HDMI_RAM_PACKET_ENABLE))
>                 return -ENODEV;
>
> -       ret = snd_pcm_hw_constraint_eld(substream->runtime,
> -                                       hdmi->connector->eld);
> +       ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
>         if (ret)
>                 return ret;
>
> @@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>
>  static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>                                     struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>
> @@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
>         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
> -       uinfo->count = sizeof(hdmi->connector->eld);
> +       uinfo->count = sizeof(connector->eld);
>
>         return 0;
>  }
> @@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
> -       memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
> -              sizeof(hdmi->connector->eld));
> +       memcpy(ucontrol->value.bytes.data, connector->eld,
> +              sizeof(connector->eld));
>
>         return 0;
>  }
> @@ -1221,7 +1220,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         struct drm_device *drm = dev_get_drvdata(master);
>         struct vc4_dev *vc4 = drm->dev_private;
>         struct vc4_hdmi *hdmi;
> -       struct vc4_hdmi_encoder *vc4_hdmi_encoder;
> +       struct drm_encoder *encoder;
>         struct device_node *ddc_node;
>         u32 value;
>         int ret;
> @@ -1230,14 +1229,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (!hdmi)
>                 return -ENOMEM;
>
> -       vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
> -                                       GFP_KERNEL);
> -       if (!vc4_hdmi_encoder)
> -               return -ENOMEM;
> -       vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
> -       hdmi->encoder = &vc4_hdmi_encoder->base.base;
> -
> +       encoder = &hdmi->encoder.base.base;
> +       hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
>         hdmi->pdev = pdev;
> +
>         hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
>         if (IS_ERR(hdmi->hdmicore_regs))
>                 return PTR_ERR(hdmi->hdmicore_regs);
> @@ -1325,15 +1320,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         }
>         pm_runtime_enable(dev);
>
> -       drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
> -       drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
> +       drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> +       drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
>
> -       hdmi->connector =
> -               vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
> -       if (IS_ERR(hdmi->connector)) {
> -               ret = PTR_ERR(hdmi->connector);
> +       ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
> +       if (ret)
>                 goto err_destroy_encoder;
> -       }
> +
>  #ifdef CONFIG_DRM_VC4_HDMI_CEC
>         hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
>                                               vc4, "vc4",
> @@ -1343,7 +1336,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret < 0)
>                 goto err_destroy_conn;
>
> -       cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
> +       cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
>         cec_s_conn_info(hdmi->cec_adap, &conn_info);
>
>         HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
> @@ -1380,10 +1373,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_delete_cec_adap:
>         cec_delete_adapter(hdmi->cec_adap);
>  err_destroy_conn:
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
>  #endif
>  err_destroy_encoder:
> -       drm_encoder_cleanup(hdmi->encoder);
> +       drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> @@ -1401,8 +1394,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         struct vc4_hdmi *hdmi = vc4->hdmi;
>
>         cec_unregister_adapter(hdmi->cec_adap);
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> -       drm_encoder_cleanup(hdmi->encoder);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
> +       drm_encoder_cleanup(&hdmi->encoder.base.base);
>
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 5ec5d1f6b1e6..17079a39f1b1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -8,6 +8,36 @@
>
>  #include "vc4_drv.h"
>
> +/* VC4 HDMI encoder KMS struct */
> +struct vc4_hdmi_encoder {
> +       struct vc4_encoder base;
> +       bool hdmi_monitor;
> +       bool limited_rgb_range;
> +};
> +
> +static inline struct vc4_hdmi_encoder *
> +to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> +}
> +
> +/* VC4 HDMI connector KMS struct */
> +struct vc4_hdmi_connector {
> +       struct drm_connector base;
> +
> +       /* Since the connector is attached to just the one encoder,
> +        * this is the reference to it so we can do the best_encoder()
> +        * hook.
> +        */
> +       struct drm_encoder *encoder;
> +};
> +
> +static inline struct vc4_hdmi_connector *
> +to_vc4_hdmi_connector(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct vc4_hdmi_connector, base);
> +}
> +
>  /* HDMI audio information */
>  struct vc4_hdmi_audio {
>         struct snd_soc_card card;
> @@ -25,8 +55,8 @@ struct vc4_hdmi_audio {
>  struct vc4_hdmi {
>         struct platform_device *pdev;
>
> -       struct drm_encoder *encoder;
> -       struct drm_connector *connector;
> +       struct vc4_hdmi_encoder encoder;
> +       struct vc4_hdmi_connector connector;
>
>         struct vc4_hdmi_audio audio;
>
> @@ -53,34 +83,4 @@ struct vc4_hdmi {
>  #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
>  #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
>
> -/* VC4 HDMI encoder KMS struct */
> -struct vc4_hdmi_encoder {
> -       struct vc4_encoder base;
> -       bool hdmi_monitor;
> -       bool limited_rgb_range;
> -};
> -
> -static inline struct vc4_hdmi_encoder *
> -to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> -{
> -       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> -}
> -
> -/* VC4 HDMI connector KMS struct */
> -struct vc4_hdmi_connector {
> -       struct drm_connector base;
> -
> -       /* Since the connector is attached to just the one encoder,
> -        * this is the reference to it so we can do the best_encoder()
> -        * hook.
> -        */
> -       struct drm_encoder *encoder;
> -};
> -
> -static inline struct vc4_hdmi_connector *
> -to_vc4_hdmi_connector(struct drm_connector *connector)
> -{
> -       return container_of(connector, struct vc4_hdmi_connector, base);
> -}
> -
>  #endif /* _VC4_HDMI_H_ */
> --
> git-series 0.9.1
diff mbox series

Patch

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index db79e0d88625..1e2214f24ed7 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -191,20 +191,15 @@  static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 	.get_modes = vc4_hdmi_connector_get_modes,
 };
 
-static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
-						     struct drm_encoder *encoder,
-						     struct i2c_adapter *ddc)
+static int vc4_hdmi_connector_init(struct drm_device *dev,
+				   struct vc4_hdmi *vc4_hdmi,
+				   struct i2c_adapter *ddc)
 {
-	struct drm_connector *connector;
-	struct vc4_hdmi_connector *hdmi_connector;
+	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
+	struct drm_connector *connector = &hdmi_connector->base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	int ret;
 
-	hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
-				      GFP_KERNEL);
-	if (!hdmi_connector)
-		return ERR_PTR(-ENOMEM);
-	connector = &hdmi_connector->base;
-
 	hdmi_connector->encoder = encoder;
 
 	drm_connector_init_with_ddc(dev, connector,
@@ -216,7 +211,7 @@  static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 	/* Create and attach TV margin props to this connector. */
 	ret = drm_mode_create_tv_margin_properties(dev);
 	if (ret)
-		return ERR_PTR(ret);
+		return ret;
 
 	drm_connector_attach_tv_margin_properties(connector);
 
@@ -228,7 +223,7 @@  static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 
 	drm_connector_attach_encoder(connector, encoder);
 
-	return connector;
+	return 0;
 }
 
 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
@@ -298,21 +293,22 @@  static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct vc4_dev *vc4 = encoder->dev->dev_private;
 	struct vc4_hdmi *hdmi = vc4->hdmi;
-	struct drm_connector_state *cstate = hdmi->connector->state;
+	struct drm_connector *connector = &hdmi->connector.base;
+	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	union hdmi_infoframe frame;
 	int ret;
 
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-						       hdmi->connector, mode);
+						       connector, mode);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return;
 	}
 
 	drm_hdmi_avi_infoframe_quant_range(&frame.avi,
-					   hdmi->connector, mode,
+					   connector, mode,
 					   vc4_encoder->limited_rgb_range ?
 					   HDMI_QUANTIZATION_RANGE_LIMITED :
 					   HDMI_QUANTIZATION_RANGE_FULL);
@@ -628,7 +624,8 @@  static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 {
-	struct drm_device *drm = hdmi->encoder->dev;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
 	unsigned long n, m;
@@ -647,7 +644,7 @@  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -685,7 +682,8 @@  static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_connector *connector = &hdmi->connector.base;
 	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
@@ -702,8 +700,7 @@  static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				VC4_HDMI_RAM_PACKET_ENABLE))
 		return -ENODEV;
 
-	ret = snd_pcm_hw_constraint_eld(substream->runtime,
-					hdmi->connector->eld);
+	ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
 	if (ret)
 		return ret;
 
@@ -717,7 +714,7 @@  static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -751,7 +748,7 @@  static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -824,7 +821,7 @@  static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
@@ -868,9 +865,10 @@  static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-	uinfo->count = sizeof(hdmi->connector->eld);
+	uinfo->count = sizeof(connector->eld);
 
 	return 0;
 }
@@ -880,9 +878,10 @@  static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
-	memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
-	       sizeof(hdmi->connector->eld));
+	memcpy(ucontrol->value.bytes.data, connector->eld,
+	       sizeof(connector->eld));
 
 	return 0;
 }
@@ -1221,7 +1220,7 @@  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *hdmi;
-	struct vc4_hdmi_encoder *vc4_hdmi_encoder;
+	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
 	u32 value;
 	int ret;
@@ -1230,14 +1229,10 @@  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (!hdmi)
 		return -ENOMEM;
 
-	vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
-					GFP_KERNEL);
-	if (!vc4_hdmi_encoder)
-		return -ENOMEM;
-	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
-	hdmi->encoder = &vc4_hdmi_encoder->base.base;
-
+	encoder = &hdmi->encoder.base.base;
+	hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
 	hdmi->pdev = pdev;
+
 	hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(hdmi->hdmicore_regs))
 		return PTR_ERR(hdmi->hdmicore_regs);
@@ -1325,15 +1320,13 @@  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	}
 	pm_runtime_enable(dev);
 
-	drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
+	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	hdmi->connector =
-		vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
-	if (IS_ERR(hdmi->connector)) {
-		ret = PTR_ERR(hdmi->connector);
+	ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
+	if (ret)
 		goto err_destroy_encoder;
-	}
+
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 					      vc4, "vc4",
@@ -1343,7 +1336,7 @@  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
+	cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
 	cec_s_conn_info(hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
@@ -1380,10 +1373,10 @@  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_delete_cec_adap:
 	cec_delete_adapter(hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(hdmi->connector);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
 #endif
 err_destroy_encoder:
-	drm_encoder_cleanup(hdmi->encoder);
+	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
@@ -1401,8 +1394,8 @@  static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	struct vc4_hdmi *hdmi = vc4->hdmi;
 
 	cec_unregister_adapter(hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(hdmi->connector);
-	drm_encoder_cleanup(hdmi->encoder);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
+	drm_encoder_cleanup(&hdmi->encoder.base.base);
 
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 5ec5d1f6b1e6..17079a39f1b1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -8,6 +8,36 @@ 
 
 #include "vc4_drv.h"
 
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+	struct vc4_encoder base;
+	bool hdmi_monitor;
+	bool limited_rgb_range;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+	struct drm_connector base;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -25,8 +55,8 @@  struct vc4_hdmi_audio {
 struct vc4_hdmi {
 	struct platform_device *pdev;
 
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
+	struct vc4_hdmi_encoder encoder;
+	struct vc4_hdmi_connector connector;
 
 	struct vc4_hdmi_audio audio;
 
@@ -53,34 +83,4 @@  struct vc4_hdmi {
 #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
 #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
 
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-	struct vc4_encoder base;
-	bool hdmi_monitor;
-	bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 #endif /* _VC4_HDMI_H_ */