Unverified Commit c98c85bb authored by Maxime Ripard's avatar Maxime Ripard
Browse files

drm/vc4: hdmi: rework connectors and encoders



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: default avatarMaxime Ripard <maxime@cerno.tech>
Tested-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Tested-by: default avatarHoegeun Kwon <hoegeun.kwon@samsung.com>
Tested-by: default avatarStefan Wahren <stefan.wahren@i2se.com>
Reviewed-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Link: https://patchwork.freedesktop.org/patch/msgid/93b418d63c876355af2b3d3afebe31a256268623.1599120059.git-series.maxime@cerno.tech
parent f73100cc
Loading
Loading
Loading
Loading
+40 −47
Original line number Diff line number Diff line
@@ -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,
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;
}
@@ -1220,7 +1219,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;
@@ -1229,14 +1228,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);
@@ -1324,15 +1319,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",
@@ -1342,7 +1335,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);
@@ -1379,10 +1372,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);
@@ -1400,8 +1393,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);
+32 −32
Original line number Diff line number Diff line
@@ -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_ */